FastAPI rejecting POST request from javascript code but not from a 3rd party request application (insomnia)
Asked Answered
O

2

3

When I use insomnia to send a post request I get a 200 code and everything works just fine, but when I send a fetch request through javascript, I get a 405 'method not allowed error', even though I've allowed post requests from the server side. (Server side code uses python).

Server side code

from pydantic import BaseModel
from typing import Optional
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = ["*"]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["POST", "GET"],
    allow_headers=["*"],
)

class data_format(BaseModel):                                                           
    comment_id : int
    username : str
    comment_body : Optional[str] = None

@app.post('/post/submit_post')
async def sumbit_post(somename_3: data_format):
    comment_id = somename_3.comment_id
    username = somename_3.username
    comment_body = somename_3.comment_body
    # add_table_data(comment_id, username, comment_body)                //Unrelated code
    return {
        'Response': 'Submission received',
        'Data' : somename_3
    }

JS code

var payload = {
    "comment_id" : 4,
    "username" : "user4",
    "comment_body": "comment_4"
};
fetch("/post/submit_post",
{
    method: "POST",
    body: JSON.stringify(payload),

    headers: {
        'Content-Type': 'application/json'
    }
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })

The error

enter image description here

What should I do to get around this error?
Thanks in advance.

Orthman answered 9/3, 2022 at 3:59 Comment(2)
What is the definition of the variable ‘origins‘ and what is the origin of your JavaScript? Seems like there is a mismatch there?Acoustic
@Acoustic that was the variable I used for the methods attribute in the middleware. Basically it was methods = origin = ['*']. I thought maybe the asterisk didn't include POST requests, so I specified it directly.Orthman
P
3

To start with, your code seems to be working just fine. The only part that had to be changed during testing it (locally) was the URL in fetch from /post/submit_post to (for instance) http://127.0.0.1:8000/post/submit_post, but I am assuming you already changed that using the domain name pointing to your app.

The 405 Method Not Allowed status code is not related to CORS. If POST was not included in the allow_methods list, the response status code would be 400 Bad Request (you could try removing it from the list to test it). From the reference above:

The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response status code indicates that the server knows the request method, but the target resource doesn't support this method.

The server must generate an Allow header field in a 405 status code response. The field must contain a list of methods that the target resource currently supports.

Thus, the 405 status code indicates that the POST request has been received and recognised by the server, but the server has rejected that specific HTTP method for that particular endpoint. Therefore, I would suggest you make sure that the decorator of the endpoint in the version you are running is defined as @app.post, as well as there is no other endpoint with the same path using @app.get. Additionally, make sure there is no any unintentional redirect happening inside the endpoint, as that would be another possible cause of that response status code. For future reference, when redirecting from a POST to GET request, the response status code has to change to 303, as shown here. Also, you could try allowing all HTTP methods with the wildcard * (i.e., allow_methods=['*']) and see how that works (even though it shouldn't be related to that). Lastly, this could also be related to the configurations of the hosting service you are running the application; thus, might be good to have a look into that as well.

Periphrasis answered 9/3, 2022 at 18:18 Comment(5)
I'm sorry but if you don't mind could you elaborate a bit further on what you mean by 'redirecting a post to a get request'? Also, I commented out all the other code in the programme so that the above code is the only thing in it but it still didn't work.Orthman
If your /post/submit_post endpoint triggers a RedirectResponse to some GET route or other domain, as shown here, this could also be a cause for that error. You said, " I commented out all the other code ". Have you restarted your application after that? Also, the code you provided works just fine. Have you tried running that code locally, as well as on the hosting service you might be using?Periphrasis
I did indeed restart the application plus I'm hosting this on my own computer. Like I said in the initial question, when I use insomnia to send a request I get back the desired response and a 200 code. It's only the JS application that doesn't work. You say that, the code works just fine, does that mean you get a 200 response when you try it? (also I'm certain there's no redirection going on).Orthman
Yes, the Javascript code works just fine and a 200 status code is returned, plus the response data from that endpoint. If it is hosted on your own PC, then why did you erase the domain in your screenshot? Are you using any other service locally? Also, have you included the domain name in the fetch URL (as described in the first paragraph of the answer above), or is it still just /post/submit_post?Periphrasis
Goddammit I mixed up the server side and JS url format. I'm really sorry for wasting your time, you're right it does work. Regarding the domain name thing, I'm still pretty new to this and I thought that was information was unique (apparently not).Orthman
M
-1

It's and old issue, described here. You need Access-Control-Request-Method: POST header in your request.

Minim answered 9/3, 2022 at 18:4 Comment(2)
I tried adding it to the header list (header list as in the one I've written in the above code right?) but it didn't work.Orthman
In fact its quite weird, even though I added it to the header list, it doesn't show up on the list of headers in the console. I tried adding a 'test' header, and that worked just fine.Orthman

© 2022 - 2024 — McMap. All rights reserved.