Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected variable evaluation on url with encoded slashes #3534

Closed
sgalam opened this issue Mar 16, 2020 · 1 comment
Closed

unexpected variable evaluation on url with encoded slashes #3534

sgalam opened this issue Mar 16, 2020 · 1 comment

Comments

@sgalam
Copy link

sgalam commented Mar 16, 2020

Issue

Hello, we found this unexpected behaviour.

Seems that in the route evaluation, the URI is url decoded at first and then the variables are evaluated.

Example1:

one variable of generic type that contain a slash encoded in %2F

curl -v http://172.23.0.2:8080/test/ab%2Fcd
@app.route('/test/<param>')
def test(param):
    return (
        f"{param}\n{request.path}",
        headers_text
    )

got: 404 Not Found
expected: HTTP 200 OK param = "ab%2Fcd" or param = "ab/cd"

Example2:

two variables of path type that contains each a slash encoded in %2F

curl -v http://172.23.0.2:8080/testp/a%2Fb/c%2Fd
@app.route('/testp/<path:param1>/<path:param2>')
def testp(param1, param2):
    return (
        f"{param1}\n{param2}\n{request.path}",
        headers_text
    )

got:
param1="a"
param2="b/c/d"

expected:
param1="a%2Fb"
param2="c%2Fd"
or
param1="a/b"
param2="c/d"

Environment

  • Python version: 3.7.7
  • Flask version: 1.1.1
  • Werkzeug version: 1.0.0

Whole code to test the examples:

# -*- coding: utf-8 -*-
​
from flask import Flask, request
​
app = Flask("TestApp")
​
headers_text = {
    "content-type": "text/plain; charset=UTF-8",
}
​​
@app.url_value_preprocessor
def test_url_value_preprocessor(endpoint, values):
    app.logger.info("test_url_value_preprocessor")
    app.logger.info(str(endpoint))
    app.logger.info(str(values))
    app.logger.info(request.url)
    app.logger.info(request.base_url)
    app.logger.info(request.path)
    app.logger.info(request.origin)
​
​
@app.route('/test/<param>')
def test(param):
    return (
        f"{param}\n{request.path}",
        headers_text
    )
​
​
@app.route('/testp/<path:param1>/<path:param2>')
def testp(param1, param2):
    return (
        f"{param1}\n{param2}\n{request.path}",
        headers_text
    )
​
​
app.run(
    host="0.0.0.0",
    port=8080,
    debug=True  # autoreload on code change
)
@davidism
Copy link
Member

davidism commented Mar 16, 2020

This is due to the WSGI spec, it's not possible to fix in Flask. See #2507, #900, pallets/werkzeug#21, and other previous discussions.

The dev server, and some production servers, provide the non-standard REQUEST_URI or RAW_URI in the environ, you might be able to write a middleware to treat that as PATH_INFO.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants