Starlette/FastApi route path components with forward slash - python

I have defined a route in Starlette/FastApi -
#router.post("/{part}")
def post_method(part):
return "ok"
#router.post("/{part}/{another_part}")
def another_post_method(part, another_part):
return "ok"
I have some forward slash in the path components, and I want to make the following request to access post_method
curl -X POST "http://127.0.0.1:5000/api/path%2Fpath" -H "accept: application/json" -d ""
results in the 404 error in the Starlette/Fastapi logs.
INFO: 127.0.0.1:50233 - "POST /api/path/path HTTP/1.1" 404
How to get the correct path components?

You can use Starlette built-in path convertor
#app.route("/path/{param:path}", name="path-convertor")

Response from Marcelo Trylesinski (Kludex) in fastapi gitter:
It is not allowed
Temporary solution: don't use path

Related

Django DRF JWT authentication get token - JSON parse error - Expecting value

I have simple Django DRF application setup which I have implemented JWT authentication.
I used the Django REST framework JWT documentation
I am using curl to test the implementation.
I can successfully get a token using the following notation used in the documentation:
$ curl -X POST -d "username=admin&password=password123" http://localhost:8000/api-token-auth/
The token is returned in following format:
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNpdHJ1Y3AiLCJleHAiOjE1MTE2NTEyMTQsInVzZXJfaWQiOjEsImVtYWlsIjoiY3VydGlzLnBva3JhbnRAZ21haWwuY29tIn0.F1TSkxe5tQVpddetUdOJDdAPP1XB9Bimb5U3c75oWd0"}
However, when I try using this other variation, I get an error:
$ curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"password123"}' http://localhost:8000/api-token-auth/
The error I get is:
{"detail":"JSON parse error - Expecting value: line 1 column 1 (char 0)"}
I also had the same error when trying to refresh or verify the token:
Refresh:
$ curl -X POST -H "Content-Type: application/json" -d '{"token":"<EXISTING_TOKEN>"}' http://localhost:8000/api-token-refresh/
Verify:
$ curl -X POST -H "Content-Type: application/json" -d '{"token":"<EXISTING_TOKEN>"}' http://localhost:8000/api-token-verify/
I was adding the token as follows:
curl -X POST -H "Content-Type: application/json" -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNpdHJ1Y3AiLCJleHAiOjE1MTE2NDg5MjIsInVzZXJfaWQiOjEsImVtYWlsIjoiY3VydGlzLnBva3JhbnRAZ21haWwuY29tIn0.T5h_PSvzvKOZCPTS60x5IUm3DgAsRCRmbMJeGWZk3Tw"}' http://localhost:8800/api-token-refresh/
Am I perhaps adding the token incorrectly? Does it need some other formatting with quotes?
Those requests are sending data in two different ways. The first request sends it as form data (x-www-form-urlencoded) which is what your endpoint is expecting and the second request sends it as application/json.
I'm not sure that the library you're using will handle a json request out of the box so one option would be to create a custom endpoint and use something like the following:
import json
def ParseFormData(self, request):
payload = json.loads(request.body.decode('utf-8'))
// use django auth to authorize request and return token
You can read more about it in this answer here: https://stackoverflow.com/a/29514222/5443056
There's instructions for manually creating auth tokens in your library's documentation. Here's the code:
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
i suggest use json.dumps({key:value})

Django JWT Auth, why one request works and the other not

I was trying Django JWT Auth and noticed that the URL responds well to one type of post but doesn't respond well to another, but i can figure out why.
Basically, if i use the cURL POST referred in the readme.md, everything goes accordingly to planned:
$ curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"abc123"}' http://localhost:8000/api-token-auth/
but if you i use another type of cURL POST with the same info, it doesn't work:
$ curl -d 'username=admin&password=abc123' http://localhost:8000/api-token-auth/
I know that the "Content-Type" is diferent, but shouldn't the request be accepted in the same manner, they are both well formed posts?
Curl's -d option actually sends the request like it's a web browser. My guess is that the URL you're testing against doesn't have a standard web form, so it can't actually process the request.
TL;DR Pretty sure Django JWT Auth doesn't support the application/x-www-form-urlencoded content type.
From curl manual:
-d --data
(HTTP) Sends the specified data in a POST request to the HTTP
server, in the same way that a browser does when a user has
filled in an HTML form and presses the submit button. This will
cause curl to pass the data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
Hope this helps!

An example of POST request in Flask API gives "Method Not Allowed"

I'm using FLASK API and I want to use POST requests.
I want just to do an example with POST requests that will return something, I keep getting an error message "Method Not Allowed".
I want to give a parameter(e.g query_params = 'name1' ) to search for a user and to return a JSON, actually I don't know where to give this parameter and I don't understand why I'm getting that message.
Here I did a simple route:
#mod_api.route('/show-user', methods=['POST'])
def show_user():
query_params = 'name1'
query = {query_params: 'Myname' }
json_resp = mongo.db.coordinates.find(query)
return Response(response=json_util.dumps(json_resp), status=200, mimetype='application/json')
Any help please?
The likely reason is that you are probably not doing a POST request against the route, which only accepts POST requests. Here is a simplified example with the mongodb details removed to illustrate this.
from flask import Flask
app = Flask(__name__)
#app.route('/show-user', methods=('POST',))
def show_user():
return "name info"
if __name__ == "__main__":
app.run(debug=True)
Now if we do a POST request it works, but if we do A GET request it raises the error you saw:
curl -H "Content-Type: application/json" -X POST -d '{}' http://127.0.0.1:5000/show-user
name info
curl -H "Content-Type: application/json" -X GET http://127.0.0.1:5000/show-user
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>

cannot generate log when use curl send post request

I am trying to test register function for my flask app.
curl -X POST -H "application/json" -d "email=12345671111#qqcom&name=test123" http://192.168.50.4:5000/register
{
"message": "\u9519\u8bef\u7684 JSON \u6570\u636e\u683c\u5f0f"
}%
The return message is very strange, and the flask log show:
"POST /register HTTP/1.1" 400 -
but if I click register button in webpage, it is normal.
192.168.50.1 - - [15/Nov/2015 13:16:49] "POST /register HTTP/1.1" 400 -
192.168.50.1 - - [15/Nov/2015 13:22:03] "OPTIONS /register HTTP/1.1" 200 -
the params is {u'fullname': u'test11828732', u'email': u'hshdshhvhd#qq.com'}
no idea for this, hope someone can help me, thanks in advance!
As the error message says, you didn't pass valid JSON data. Your curl command is incorrect: you didn't set the content type header correctly and you passed form encoded data rather than JSON data.
curl -X POST -H 'Content-Type: application/json' -d '{"email": "12345671111#qq.com", "name": "test123"}'

Body in Request ignored when forming POST dict in Django

I am working on a Django server that takes an integer from POST data. If I send the integer via GET there's no problems, but it gets dropped when sent via POST.
I run the server with:
./manage.py runserver 0.0.0.0:8000
and then generate the POST request with:
curl -X POST -H "Content-Type: application/json" -d '{"myInt":4}' "http://0.0.0.0:8000/myURL/"
I am using PDB in the view, and here is the result I am getting for the following commands:
request.method
> 'POST'
request.body
> '{"myInt":4}'
request.POST
> <QueryDict: {}>
I have used #csrf_exempt as a decorator for the view, just to make sure that isn't causing any problems.
Currently it is baffling me that request.POST does not contain myInt, is my POST request not well-formed?
Your post request is sending JSON not application/x-www-form-urlencoded
If you look at the django docs about HttpRequest.POST .
A dictionary-like object containing all given HTTP POST parameters, providing that the request contains form data. See the QueryDict documentation below. If you need to access raw or non-form data posted in the request, access this through the HttpRequest.body attribute instead.
You need to POST form encoded data. I didn't test this and haven't used curl in a while, but I believe the following should work.
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "myInt=4" "http://0.0.0.0:8000/myURL/"

Categories