Skip to content

Commit

Permalink
Fixes #4649 Internal proxy handling of relative URL segments breaks MS2
Browse files Browse the repository at this point in the history
Adds the 'hyperlink' package to properly resolve URLs with relative
parts when using the internal proxy.
  • Loading branch information
Tobias committed Jul 20, 2019
1 parent 66f63e2 commit c7946a9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
23 changes: 23 additions & 0 deletions geonode/proxy/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
from django.contrib.auth import get_user_model
from django.test.utils import override_settings

from mock import MagicMock


TEST_DOMAIN = '.github.com'
TEST_URL = 'https://help%s/' % TEST_DOMAIN
Expand Down Expand Up @@ -94,6 +96,27 @@ def test_validate_remote_services_hosts(self):
# 200 - FOUND
self.assertTrue(response.status_code in (200, 301))

@override_settings(DEBUG=False, PROXY_ALLOWED_HOSTS=('.example.org',))
def test_relative_urls(self):
"""Proxying to a URL with a relative path element should normalise the path into
an absolute path before calling the remote URL."""
import geonode.proxy.views

class Response(object):
status_code = 200
content = 'Hello World'
headers = {'Content-Type': 'text/html'}

request_mock = MagicMock()
request_mock.return_value = (Response(), None)

geonode.proxy.views.http_client.request = request_mock
url = "http://example.org/test/test/../../index.html"

self.client.get('%s?url=%s' % (self.proxy_url, url))
assert request_mock.assert_called_once
assert request_mock.call_args[0][0] == 'http://example.org/index.html'


class OWSApiTestCase(GeoNodeBaseTestSupport):

Expand Down
8 changes: 8 additions & 0 deletions geonode/proxy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import tempfile
import traceback

from hyperlink import URL
from slugify import slugify
from urlparse import urlparse, urlsplit, urljoin

Expand Down Expand Up @@ -227,6 +228,13 @@ def proxy(request, url=None, response_callback=None,

_url = parsed.geturl()

# Some clients / JS libraries generate URLs with relative URL paths, e.g.
# "http://host/path/path/../file.css", which the requests library cannot
# currently handle (https://github.com/kennethreitz/requests/issues/2982).
# We parse and normalise such URLs into absolute paths before attempting
# to proxy the request.
_url = URL.from_text(_url).normalize().to_text()

if request.method == "GET" and access_token and 'access_token' not in _url:
query_separator = '&' if '?' in _url else '?'
_url = ('%s%saccess_token=%s' %
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ amqp==2.4.2
pyyaml>=4.2b1
beautifulsoup4==4.7.1
httplib2<=0.10.3
hyperlink==19.0.0
idna<2.7>=2.5
urllib3==1.24.2
Paver==1.3.4
python-slugify==3.0.2
Expand Down

0 comments on commit c7946a9

Please sign in to comment.