I’m trying to implement a custom API to handle requests from the client (to upload files). I’ve figured out how to route the custom endpoint, but I can’t figure out how to access the request body. Here’s an excerpt of a working endpoint:
app = Dash("demo")
server = app.server
@server.put('/api/contents/<dest_dir>/<dest_file>')
def upload_audio(dest_dir, dest_file):
"""
REST API to upload new .webm audio file
{
"path": dest_path,
"type": "file",
"format": "base64",
"content": base64Blob
}
"""
print(f"upload_audio with {(dest_dir, dest_file)}")
return {"status": "short circuit"}, 404
But when I try to access the request body the way the Flask documentation suggests it throws an error
@server.put('/api/contents/<dest_dir>/<dest_file>')
def upload_audio(dest_dir, dest_file):
"""
REST API to upload new .webm audio file
{
"path": dest_path,
"type": "file",
"format": "base64",
"content": base64Blob
}
"""
print(f"upload_audio with {(dest_dir, dest_file)}")
request_json = request.json # I really hate this globals pattern. Why don't you just pass an object?
I get a response from Werkzeug about referencing an unknown variable
<!doctype html>
...
<h1>NameError</h1>
<div class="detail">
<p class="errormsg">NameError: name 'request' is not defined
</p>
</div>
<h2 class="traceback">Traceback <em>(most recent call last)</em></h2>
<div class="traceback noframe-traceback">
<h3></h3>
<ul></ul>
<blockquote>NameError: name 'request' is not defined
</blockquote>
</div>
...
How can I write a PUT api with plotly dash and access the request body?
Hello @xaviersjs,
You can use a clientside callback to create a custom fetch request to the endpoint that you’ve built.
I don’t think I understand. Clientside callbacks are just javascript running in the browser, right? I already have javascript running in a browser which is trying to call a PUT request on the server. It’s the server-side PUT request that I’m trying to implement.
Can you provide an example of how you would use clientside_callback
to call upload_audio()
?
Alright.
Flask doesn’t use route.put, it should be @server.route(route,methods=‘put’)
Yes it does
https://flask.palletsprojects.com/en/3.0.x/api/#flask.Flask.put
I think you’re missing the point of the question. I can already access the API. It works. The problem is accessing the body of the request object. I have sent an application/json
PUT request to the server. The server prints out to the console when the request is received. But if I try to access request.json
the application complains that request
doesn’t exist.
I got this by trying to use the “global request object” from the flask documentation Quickstart — Flask Documentation (3.0.x)
In Flask this information is provided by the global request
object. If you have some experience with Python you might be wondering how that object can be global and how Flask manages to still be threadsafe. The answer is context locals:
The problem I’m having is figuring out how to access the request object in Dash. It seems Dash changes some of the ways that Flask operates by default. What is the way that Dash suggests we access the contents of a request from an arbitrary endpoint that isn’t a callback?
Ok, I see the problem now. I wasn’t importing the global request object. From Quickstart — Flask Documentation (3.0.x)
First of all you have to import it from the flask
module:
from flask import request
That means the request works if I change my above example to
from dash import Dash
from flask import request # <<< This was missing entirely
app = Dash("demo")
server = app.server
@server.put('/api/contents/<dest_dir>/<dest_file>')
def upload_audio(dest_dir, dest_file):
print(f"upload_audio with {(dest_dir, dest_file)}")
request_json = request.json
...
1 Like
Was missing that part of your code.