Search code examples
httpflaskcurlhttp-status-code-404http-status-codes

Server responding with status code 200 when 405 was expected


I'd like to understand why I'm getting a 200 status code here. I'm running a flask app and getting a 200 status code as response when requesting to a handled endpoint but not a handled method.

This is the minimal, reproducible code. app.py file:

from flask import Flask, request, abort, jsonify
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, String, Integer

def create_app():
    db = SQLAlchemy()
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://postgres:postgres@localhost:5432/so_question"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    db = SQLAlchemy()
    db.app = app
    db.init_app(app)
    db.create_all()

    class Book(db.Model):  
        __tablename__ = 'books'

        id = Column(Integer, primary_key=True)

        def __init__(self, id):
            self.id = id

        def format(self):
            return {
            'id': self.id,
            }

    @app.route('/books')
    def get_books():
        books = Book.query.order_by(Book.id).all()
        return jsonify({
            'books': [book.format() for book in books],
        })

    @app.route('/books/<int:book_id>', methods=["PATCH"])
    def update_title(book_id):
        return jsonify({
            'success': True
        })

    @app.errorhandler(405)
    def not_allowed(error):
        return jsonify({
            "success": False,
        })
    
    return app

Then I ran FLASK_APP=app.py flask run. I made the following request: curl -X GET http://127.0.0.1:5000/books and this is the result:

{
  "books": [
    {
      "id": 1
    }, 
    {
      "id": 2
    }
  ]
}

But here is what I don't understand: I'm not handling a POST request to the /books/<int:book_id endpoint and actually if I make that request: curl -X POST http://127.0.0.1:5000/books/2 the 404 error handler manages the response. What I'm not understanding is why the server responds with "POST /books/2 HTTP/1.1" 200 -. Why the 200 status code to this error that is actually being detected as an error (because the response is being handled by the 405 error handler).?

I'm pretty sure the answer is related with this post but here I'm asking why is this happening not how is fixed or what's supposed to be the best status code for this issue.


Solution

  • Returning without a status code will default to code 200

        def not_allowed(error):
            return jsonify({
                "success": False,
            })
    

    This function should return your desired status code.

    return jsonify({"success": False}), 405

    See previously answered question.