Skip to content

Don't accidently create relative links#1538

Closed
hefee wants to merge 2 commits intopallets:masterfrom
netzguerilla:absolute-redirects
Closed

Don't accidently create relative links#1538
hefee wants to merge 2 commits intopallets:masterfrom
netzguerilla:absolute-redirects

Conversation

@hefee
Copy link
Copy Markdown

@hefee hefee commented May 11, 2019

append_slash_redirect should not change absolute links to relative ones.
That breaks serving applications via nginx.

e.g.
PATH_INFO="/help/test" -> the Location would be "help/test/" and this is translated correctly by nginx to:
https://example.com/help/help/test

append_slash_redirect should not change absolute links to relative ones.
That breaks serving applications via nginx.

e.g.
PATH_INFO="/help/test"  -> the Location would be "help/test/" and this is translated correctly by nginx to:
https://example.com/help/help/test
@davidism
Copy link
Copy Markdown
Member

Please add tests and a changelog.

@davidism
Copy link
Copy Markdown
Member

I'm not super clear what issue you're fixing based on your description. Fairly sure this is intentional, SCRIPT_NAME and PATH_INFO will be combined later in the response and will always create an absolute path.

@hefee
Copy link
Copy Markdown
Author

hefee commented May 16, 2019

@davidism at least in my case this doesn't work.

see here the environ:

{'HTTP_ACCEPT': '*/*', 'werkzeug.request': <Request 'https://example.com/help/foo' [GET]>, 'wsgi.run_once': False, 'CONTENT_TYPE': '', 'wsgi.errors': <_io.TextIOWrapper name=2
 mode='w' encoding='UTF-8'>, 'PATH_INFO': '/help/foo', 'wsgi.url_scheme': 'https', 'CONTENT_LENGTH': '', 'REQUEST_URI': '/help/foo', 'SERVER_NAME': 'example.com',
 'uwsgi.node': b'xx.example.com', 'HTTP_ACCEPT_ENCODING': 'identity', 'SCRIPT_NAME': '/', 'HTTP_HOST': 'example.com', 'HTTP_USER_AGENT': 'Wget/1.20.1 (linux-gnu)', 'REQUEST_METHOD':
'GET', 'HTTP_AUTHORIZATION': 'Basic XXXXXXXXXXXXXX', 'SERVER_PORT': '443', 'QUERY_STRING': '', 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'SERVER_PROTOCOL': 'HTTP/1.1', 'REMOTE_A
DDR': '1::1', 'uwsgi.version': b'2.0.14-debian', 'HTTP_CONNECTION': 'Keep-Alive', 'REMOTE_PORT': '43586', 'HTTPS': 'on', 'REQUEST_SCHEME': 'https', 'wsgi.input': <uws
gi._Input object at 0x7f92b539bb10>, 'wsgi.file_wrapper': <built-in function uwsgi_sendfile>, 'wsgi.version': (1, 0), 'DOCUMENT_ROOT': '/pathto'} 

So far I see SCRIPT_NAME is not anywhere used within the redirect function, that's why I'm wondering who is responsible to create absolute links?

My setup is nginx <-> uwsgi <-> flask/werkzeug

@davidism
Copy link
Copy Markdown
Member

davidism commented May 16, 2019

redirect returns a Response. When Response generates headers, it adjusts the Location header to make it absolute.

# make sure the location header is an absolute URL
if location is not None:
old_location = location
if isinstance(location, text_type):
# Safe conversion is necessary here as we might redirect
# to a broken URI scheme (for instance itms-services).
location = iri_to_uri(location, safe_conversion=True)
if self.autocorrect_location_header:
current_url = get_current_url(environ, strip_querystring=True)
if isinstance(current_url, text_type):
current_url = iri_to_uri(current_url)
location = url_join(current_url, location)
if location != old_location:
headers["Location"] = location

@hefee hefee force-pushed the absolute-redirects branch from d731ab5 to ca99479 Compare May 16, 2019 19:42
@hefee
Copy link
Copy Markdown
Author

hefee commented May 16, 2019

redirect returns a Response. When Response generates headers, it adjusts the Location header to make it absolute.

# make sure the location header is an absolute URL
if location is not None:
old_location = location
if isinstance(location, text_type):
# Safe conversion is necessary here as we might redirect
# to a broken URI scheme (for instance itms-services).
location = iri_to_uri(location, safe_conversion=True)
if self.autocorrect_location_header:
current_url = get_current_url(environ, strip_querystring=True)
if isinstance(current_url, text_type):
current_url = iri_to_uri(current_url)
location = url_join(current_url, location)
if location != old_location:
headers["Location"] = location

okay than it is wekrzeug, who creates the absolute url wrongly ;D

See line 607:

location = url_join(current_url, location)

current_url = "https://example.com/help/foo"
location = "help/foo"

-> location = "https://example.com/help/help/foo"

IMO current_url is wrong to use there, instead SCRIPT_NAME needs to been taking into account.

@davidism
Copy link
Copy Markdown
Member

The current behavior is correct. In WSGI, paths are typically relative to the script_root, which is defined by the base_url in the test client. append_slash_redirect is within the context of the current environ.

@davidism davidism closed this Jul 13, 2019
@hefee
Copy link
Copy Markdown
Author

hefee commented Jul 13, 2019

@davidism: can you point me to some documentation for this?

I still think absolute links needs to handled different than relative ones. As in the case I need this fix 'SCRIPT_NAME' is '/' and 'PATH_INFO' is '/help/foo'. And I need to create a link to '/nonhelp'. With the current implementation I never can create links to '/nonhelp', as I always end up in '/help/nonhelp'. But '/nonhelp is still in namespace of SCRIPT_NAME and that means it is a valid PATH_INFO to request for.
Unfortunately I don't understand how SCRIPT_NAME and PATH_INFO are translated into base_url.

@oztourer
Copy link
Copy Markdown

I cannot agree that the current code works correctly. If the URL passed to append_slash_redirect() begins with a leading slash it is an absolute URL and the slash should not be removed. The URL should remain absolute or relative after the function completes.

I believe this is a coding error, strip() has been used instead of rstrip(). The only reason that strip() is called at all is to ensure that the returned URL does not end up with two trailing slashes.

So, to my mind, line 542 currently uses strip('/') but should use rstrip:

new_path = environ["PATH_INFO"].rstrip("/") + "/"

@jab jab reopened this Jul 18, 2020
@davidism davidism closed this Jul 18, 2020
@davidism
Copy link
Copy Markdown
Member

This is an issue with your use of the function and the wsgi environ, not with the function itself. There's another discussion that goes into more detail, but I'm on my phone and can't find it right now. Suffice to say, I've looked into this in depth and concluded there is not an issue.

@pallets pallets deleted a comment from oztourer Jul 18, 2020
@pallets pallets deleted a comment from oztourer Jul 18, 2020
@pallets pallets locked and limited conversation to collaborators Jul 18, 2020
@davidism
Copy link
Copy Markdown
Member

Addressed in #2338

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants