Matthew Moisen
Matthew Moisen

Reputation: 18279

Flask POSTs with Trailing Slash

The documentation states that the preferred way to define a route is to include a trailing slash:

@app.route('/foo/', methods=['GET'])
def get_foo():
    pass

This way, a client can GET /foo or GET /foo/ and receive the same result.

However, POSTed methods do not have the same behavior.

from flask import Flask
app = Flask(__name__)

@app.route('/foo/', methods=['POST'])
def post_foo():
    return "bar"

app.run(port=5000)

Here, if you POST /foo, it will fail with method not allowed if you are not running in debug mode, or it will fail with the following notice if you are in debug mode:

A request was sent to this URL (http://localhost:5000/foo) but a redirect was issued automatically by the routing system to "http://localhost:5000/foo/". The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one. Make sure to directly send your POST-request to this URL since we can't make browsers or HTTP clients redirect with form data reliably or without user interaction


Moreover, it appears that you cannot even do this:

@app.route('/foo', methods=['POST'])
@app.route('/foo/', methods=['POST'])
def post_foo():
    return "bar"

Or this:

@app.route('/foo', methods=['POST'])
def post_foo_no_slash():
    return redirect(url_for('post_foo'), code=302)

@app.route('/foo/', methods=['POST'])
def post_foo():
    return "bar"

Is there any way to get POST to work on both non-trailing and trailing slashes?

Upvotes: 10

Views: 4668

Answers (3)

Vasu
Vasu

Reputation: 31

Flask does not enforce the inclusion of a trailing slash in routes, and using or omitting a trailing slash should not pose any issues.

If you are accessing these routes through a web browser, keep in mind that browsers typically use the GET method by default. So that you will receive <HTTP 405> method not allowed

The choice depends entirely on your specific use case. If you intend to access these routes through a web browser, then you may need to modify them to accept the GET method.

For more information about the behavior of trailing slashes in Flask, you can refer to the documentation here: Flask Trailing Slash Behavior.

Upvotes: 0

Wojciech Jakubas
Wojciech Jakubas

Reputation: 1663

Please refer to this post: Trailing slash triggers 404 in Flask path rule

You can disable strict slashes to support your needs

Globally:

app = Flask(__name__)
app.url_map.strict_slashes = False

... or per route

@app.route('/foo', methods=['POST'], strict_slashes=False)
def foo():
    return 'foo'

You can also check this link. There is separate discussion on github on this one. https://github.com/pallets/flask/issues/1783

Upvotes: 25

metmirr
metmirr

Reputation: 4302

You can check request.path whether /foo/ or not then redirect it to where you want:

@app.before_request
def before_request():
    if request.path == '/foo':
        return redirect(url_for('foo'), code=123)

@app.route('/foo/', methods=['POST'])
def foo():
    return 'foo'

$ http post localhost:5000/foo 
127.0.0.1 - - [08/Mar/2017 13:06:48] "POST /foo HTTP/1.1" 123

Upvotes: 1

Related Questions