1+ """
2+ Test for reproducing the curl upload issue described in the problem statement.
3+ """
4+ import anyio
5+ import httpx
6+ import pytest
7+ import tempfile
8+ import os
9+
10+ from tests .helpers import generate_test_file
11+
12+
13+ @pytest .mark .anyio
14+ async def test_curl_upload_missing_content_length (test_client : httpx .AsyncClient ):
15+ """Tests HTTP upload when Content-Length header is missing (simulating curl issue)."""
16+ uid = "curl-no-content-length"
17+ file_content , file_metadata = generate_test_file (size_in_kb = 64 )
18+
19+ # Simulate curl upload without Content-Length header (one potential issue)
20+ headers = {
21+ 'Content-Type' : file_metadata .type ,
22+ # Missing Content-Length - some curl configurations might not set this
23+ }
24+
25+ response = await test_client .put (
26+ f"/{ uid } /{ file_metadata .name } " ,
27+ content = file_content ,
28+ headers = headers
29+ )
30+
31+ # This should fail with 400 due to missing/invalid metadata
32+ assert response .status_code == 400
33+ assert "Invalid file metadata" in response .text or "Cannot decode file metadata" in response .text
34+
35+
36+ @pytest .mark .anyio
37+ async def test_curl_upload_missing_content_type (test_client : httpx .AsyncClient ):
38+ """Tests HTTP upload when Content-Type header is missing (simulating curl issue)."""
39+ uid = "curl-no-content-type"
40+ file_content , file_metadata = generate_test_file (size_in_kb = 64 )
41+
42+ # Simulate curl upload without Content-Type header (another potential issue)
43+ headers = {
44+ 'Content-Length' : str (file_metadata .size ),
45+ # Missing Content-Type - curl might not set this for unknown file types
46+ }
47+
48+ response = await test_client .put (
49+ f"/{ uid } /{ file_metadata .name } " ,
50+ content = file_content ,
51+ headers = headers
52+ )
53+
54+ # This might work if Content-Type defaults properly, or fail
55+ print (f"Response status: { response .status_code } " )
56+ print (f"Response text: { response .text } " )
57+
58+
59+ @pytest .mark .anyio
60+ async def test_curl_upload_zero_content_length (test_client : httpx .AsyncClient ):
61+ """Tests HTTP upload when Content-Length is 0 (potential curl issue)."""
62+ uid = "curl-zero-length"
63+ file_content , file_metadata = generate_test_file (size_in_kb = 64 )
64+
65+ # Simulate wrong Content-Length (could happen with curl misuse)
66+ headers = {
67+ 'Content-Type' : file_metadata .type ,
68+ 'Content-Length' : '0' , # Wrong content length
69+ }
70+
71+ response = await test_client .put (
72+ f"/{ uid } /{ file_metadata .name } " ,
73+ content = file_content ,
74+ headers = headers
75+ )
76+
77+ # This should fail with 400 due to size validation (gt=0)
78+ assert response .status_code == 400
79+ assert "Invalid file metadata" in response .text
80+
81+
82+ @pytest .mark .anyio
83+ async def test_curl_upload_short_filename (test_client : httpx .AsyncClient ):
84+ """Tests HTTP upload with a very short filename (potential validation issue)."""
85+ uid = "curl-short-name"
86+ file_content , file_metadata = generate_test_file (size_in_kb = 64 )
87+
88+ # Simulate upload with very short filename
89+ short_filename = "a" # Only 1 character - should fail min_length=2 validation
90+ headers = {
91+ 'Content-Type' : file_metadata .type ,
92+ 'Content-Length' : str (file_metadata .size ),
93+ }
94+
95+ response = await test_client .put (
96+ f"/{ uid } /{ short_filename } " ,
97+ content = file_content ,
98+ headers = headers
99+ )
100+
101+ # This should fail with 400 due to filename validation
102+ assert response .status_code == 400
103+ assert "Invalid file metadata" in response .text
104+
105+
106+ @pytest .mark .anyio
107+ async def test_curl_upload_with_expect_100_continue (test_client : httpx .AsyncClient ):
108+ """Tests HTTP upload with Expect: 100-continue header (like curl --expect100-timeout)."""
109+ uid = "curl-expect-100"
110+ file_content , file_metadata = generate_test_file (size_in_kb = 64 )
111+
112+ # Simulate curl with --expect100-timeout flag
113+ headers = {
114+ 'Content-Type' : file_metadata .type ,
115+ 'Content-Length' : str (file_metadata .size ),
116+ 'Expect' : '100-continue' , # This header is set by curl --expect100-timeout
117+ }
118+
119+ async def sender ():
120+ response = await test_client .put (
121+ f"/{ uid } /{ file_metadata .name } " ,
122+ content = file_content ,
123+ headers = headers
124+ )
125+ print (f"Upload response status: { response .status_code } " )
126+ print (f"Upload response text: { response .text } " )
127+ return response
128+
129+ async def receiver ():
130+ await anyio .sleep (1.0 ) # Wait for upload to start
131+ response = await test_client .get (f"/{ uid } ?download=true" )
132+ print (f"Download response status: { response .status_code } " )
133+ return response
134+
135+ async with anyio .create_task_group () as tg :
136+ tg .start_soon (sender )
137+ tg .start_soon (receiver )
0 commit comments