Search code examples
javascriptpythonhttphttprequestfastapi

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


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.


Solution

  • 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 recognized 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.