Opened 3 years ago

Last modified 3 years ago

#32567 assigned Bug

Issues with ":" and "|" characters in URLs when using LiveServerTestCase on Windows

Reported by: Tim G Owned by: Tim G
Component: Testing framework Version: 3.1
Severity: Normal Keywords: windows, liveservertestcase, path
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by Tim G)

I am using Python 3.8 32-bit on Windows: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)] on win32

I installed Django and requests in a virtual environment:
pip install django requests

My virtual environment now has:

asgiref==3.3.1
certifi==2020.12.5
chardet==4.0.0
Django==3.1.7
idna==2.10
pytz==2021.1
requests==2.25.1
sqlparse==0.4.1
urllib3==1.26.4

I created a new Django project:

django-admin.exe startproject example
cd example
django-admin.exe startapp livecase

I used the following code in my example/livecase/views.py:

from django.http import HttpResponse

def example(request):
    return HttpResponse("OK")

And the following in example/example/urls.py:

from django.contrib import admin
from django.urls import path
from livecase.views import example

urlpatterns = [
    path('test:12345/', example),
    path('admin/', admin.site.urls),
]

I then used the following code in example/livecase/tests.py:

from django.test import LiveServerTestCase
import requests

class MyTest(LiveServerTestCase):
    def test_example(self):
        r = requests.get(f"{self.live_server_url}/test:12345/")
        self.assertEqual(r.status_code, 200)

I run the tests: python manage.py test

I get the following error, with the traceback:

Traceback (most recent call last):
  File "C:\[redacted]\AppData\Local\Programs\Python\Python38-32\lib\wsgiref\handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
  File "C:\[redacted]\venv-test\lib\site-packages\django\test\testcases.py", line 1324, in __call__
    return self.application(environ, start_response)
  File "C:\[redacted]\venv-test\lib\site-packages\django\test\testcases.py", line 1325, in __call__
    return super().__call__(environ, start_response)
  File "C:\[redacted]\venv-test\lib\site-packages\django\core\handlers\wsgi.py", line 133, in __call__
    response = self.get_response(request)
  File "C:\[redacted]\venv-test\lib\site-packages\django\test\testcases.py", line 1305, in get_response
    return self.serve(request)
  File "C:\[redacted]\venv-test\lib\site-packages\django\test\testcases.py", line 1320, in serve
    return serve(request, final_rel_path, document_root=self.get_base_dir())
  File "C:\[redacted]\venv-test\lib\site-packages\django\views\static.py", line 38, in serve
    fullpath = Path(safe_join(document_root, path))
  File "C:\[redacted]\venv-test\lib\site-packages\django\utils\_os.py", line 29, in safe_join
    raise SuspiciousFileOperation(
django.core.exceptions.SuspiciousFileOperation: The joined path (T:\12345) is located outside of the base path component (C:\[redacted]\example)
F
======================================================================
FAIL: test_example (livecase.tests.MyTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\[redacted]\example\livecase\tests.py", line 9, in test_example
    self.assertEqual(r.status_code, 200)
AssertionError: 500 != 200

----------------------------------------------------------------------
Ran 1 test in 0.528s

If I use "|" instead of ":" in the URL in the test case, the same problem happens.
If I use self.client.get, the test passes and no exception is raised.

I tried to replicate the issue in a Linux environment, and I was not able to (although using Python 3.8 64 bit).

I believe the path conversion issue is happening at https://github.com/django/django/blob/45814af6197cfd8f4dc72ee43b90ecde305a1d5a/django/test/testcases.py#L1438

Thanks.

Change History (10)

comment:1 by Tim G, 3 years ago

To illustrate the problem better, I added one (failing) test in the test suite:

https://github.com/timoguic/django/commits/ticket_32567/tests/staticfiles_tests/test_liveserver.py

comment:2 by Tim G, 3 years ago

Description: modified (diff)

comment:3 by Carlton Gibson, 3 years ago

Hey Tim, nice report thanks.

I didn't have the time to assess yet, but a couple of questions:

  1. Did you examine request.path there — what's it look like? What about request.META?
  2. Does it happen with runserver hitting the URL by hand?
Last edited 3 years ago by Carlton Gibson (previous) (diff)

comment:4 by Carlton Gibson, 3 years ago

Triage Stage: UnreviewedAccepted

Reproduced on Windows 10 (64bit) with the test case provided. Test passes on macOS.

Tim do you fancy opening a PR with the test at least, so that it's easier to work with?

Thanks again for the report. Really very clear.

Last edited 3 years ago by Carlton Gibson (previous) (diff)

in reply to:  4 comment:5 by Tim G, 3 years ago

Replying to Carlton Gibson:

Tim do you fancy opening a PR with the test at least, so that it's easier to work with?

Sure. I just did that.
https://github.com/django/django/pull/14146

I think I found a fix, but I am not sure if it's the right approach. Shall I commit in the PR still?

Last edited 3 years ago by Tim G (previous) (diff)

comment:6 by Carlton Gibson, 3 years ago

Hey Tim. Yes, do. It’ll highlight what’s going on. We can assess it in review.
Thanks!

comment:8 by Mariusz Felisiak, 3 years ago

Type: UncategorizedBug

comment:9 by Jacob Walls, 3 years ago

Has patch: set

comment:10 by Mariusz Felisiak, 3 years ago

Owner: changed from nobody to Tim G
Patch needs improvement: set
Status: newassigned
Note: See TracTickets for help on using tickets.
Back to Top