@@ -28,4 +28,154 @@ def test_large_uploads
2828 file . close
2929 file . unlink
3030 end
31+
32+ def test_mixed_uploads_stress_test
33+ requests = [ ]
34+
35+ info_get_requests = Array . new ( 200 ) do
36+ Typhoeus ::Request . new ( "http://127.0.0.1:9080/api/info/" , http_options . deep_merge ( {
37+ headers : {
38+ "X-Unique" => SecureRandom . hex ( 40 ) ,
39+ } ,
40+ } ) )
41+ end
42+ requests += info_get_requests
43+
44+ read_body_requests = { }
45+ unread_body_requests = { }
46+ multipart_body_requests = { }
47+ above_max_body_size_requests = { }
48+
49+ [ :post , :put , :patch ] . each do |method |
50+ read_body_requests [ method ] = Array . new ( 5 ) do
51+ body = SecureRandom . random_bytes ( 5 * 1024 * 1024 + rand ( -200 ..200 ) ) . freeze # 5MB
52+ Typhoeus ::Request . new ( "http://127.0.0.1:9080/api/read-body" , http_options . deep_merge ( {
53+ method : method ,
54+ body : body ,
55+ headers : {
56+ "Content-Type" => "text/plain" ,
57+ "X-Expected-Body-Size" => body . bytesize ,
58+ "X-Expected-Body-Checksum" => Digest ::SHA256 . hexdigest ( body ) ,
59+ } ,
60+ } ) )
61+ end
62+ requests += read_body_requests [ method ]
63+
64+ unread_body_requests [ method ] = Array . new ( 5 ) do
65+ body = SecureRandom . random_bytes ( 5 * 1024 * 1024 + rand ( -200 ..200 ) ) . freeze # 5MB
66+ Typhoeus ::Request . new ( "http://127.0.0.1:9080/api/unread-body" , http_options . deep_merge ( {
67+ method : method ,
68+ body : body ,
69+ headers : {
70+ "Content-Type" => "text/plain" ,
71+ "X-Expected-Body-Size" => body . bytesize ,
72+ } ,
73+ } ) )
74+ end
75+ requests += unread_body_requests [ method ]
76+
77+ multipart_body_requests [ method ] = Array . new ( 5 ) do
78+ file = Tempfile . new ( "large" )
79+ body = SecureRandom . random_bytes ( 5 * 1024 * 1024 + rand ( -200 ..200 ) ) . freeze # 5MB
80+ file . write ( body )
81+ Typhoeus ::Request . new ( "http://127.0.0.1:9080/api/upload" , http_options . deep_merge ( {
82+ # Workaround for PUT not working with Typhoeus and multipart uploads
83+ # currently:
84+ # https://github.com/typhoeus/typhoeus/issues/389#issuecomment-3186406150
85+ method : :post ,
86+ customrequest : method . to_s . upcase ,
87+ body : { upload : file } ,
88+ headers : {
89+ "X-Expected-Body-Size" => body . bytesize ,
90+ "X-Expected-Body-Checksum" => Digest ::SHA256 . hexdigest ( body ) ,
91+ } ,
92+ } ) )
93+ end
94+ requests += multipart_body_requests [ method ]
95+
96+ above_max_body_size_requests [ method ] = Array . new ( 5 ) do
97+ body = SecureRandom . random_bytes ( 5 * 1024 * 1024 + rand ( -200 ..200 ) ) . freeze # 5MB
98+ Typhoeus ::Request . new ( "https://127.0.0.1:9081/api-umbrella/v1/users" , http_options . deep_merge ( {
99+ method : method ,
100+ body : body ,
101+ headers : {
102+ "Content-Type" => "text/plain" ,
103+ } ,
104+ } ) )
105+ end
106+ requests += above_max_body_size_requests [ method ]
107+ end
108+
109+ hydra = Typhoeus ::Hydra . new ( max_concurrency : 10 )
110+ requests . shuffle
111+ requests . each do |request |
112+ hydra . queue ( request )
113+ end
114+ hydra . run
115+
116+ requests . each do |request |
117+ puts request . response . code
118+ end
119+
120+ assert_equal ( 200 , info_get_requests . length )
121+ info_get_requests . each do |request |
122+ assert_response_code ( 200 , request . response )
123+ request_headers = request . original_options . fetch ( :headers )
124+ data = MultiJson . load ( request . response . body )
125+ assert_equal ( request_headers . fetch ( "X-Unique" ) , data . fetch ( "headers" ) . fetch ( "x-unique" ) )
126+ end
127+
128+ assert_equal ( 3 , read_body_requests . length )
129+ read_body_requests . each do |method , method_requests |
130+ assert_equal ( 5 , method_requests . length )
131+ method_requests . each do |request |
132+ assert_response_code ( 200 , request . response )
133+ request_headers = request . original_options . fetch ( :headers )
134+ data = MultiJson . load ( request . response . body )
135+ assert_equal ( request . original_options . fetch ( :method ) . to_s . upcase , data . fetch ( "method" ) )
136+ assert_equal ( "text/plain" , data . fetch ( "headers" ) . fetch ( "content-type" ) )
137+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Size" ) . to_s , data . fetch ( "headers" ) . fetch ( "content-length" ) )
138+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Size" ) , data . fetch ( "body_size" ) )
139+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Checksum" ) , data . fetch ( "body_checksum" ) )
140+ end
141+ end
142+
143+ assert_equal ( 3 , unread_body_requests . length )
144+ unread_body_requests . each do |method , method_requests |
145+ assert_equal ( 5 , method_requests . length )
146+ method_requests . each do |request |
147+ assert_response_code ( 200 , request . response )
148+ request_headers = request . original_options . fetch ( :headers )
149+ data = MultiJson . load ( request . response . body )
150+ assert_equal ( request . original_options . fetch ( :method ) . to_s . upcase , data . fetch ( "method" ) )
151+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Size" ) . to_s , data . fetch ( "http_content_length" ) )
152+ refute ( data . key? ( "body_size" ) )
153+ refute ( data . key? ( "body_checksum" ) )
154+ end
155+ end
156+
157+ assert_equal ( 3 , multipart_body_requests . length )
158+ multipart_body_requests . each do |method , method_requests |
159+ assert_equal ( 5 , method_requests . length )
160+ method_requests . each do |request |
161+ assert_response_code ( 200 , request . response )
162+ request_headers = request . original_options . fetch ( :headers )
163+ data = MultiJson . load ( request . response . body )
164+ assert_equal ( request . original_options . fetch ( :customrequest ) . to_s . upcase , data . fetch ( "method" ) )
165+ assert_match ( "multipart/form-data; boundary=" , data . fetch ( "headers" ) . fetch ( "content-type" ) )
166+ assert_in_delta ( request_headers . fetch ( "X-Expected-Body-Size" ) , data . fetch ( "headers" ) . fetch ( "content-length" ) . to_i , 400 )
167+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Size" ) , data . fetch ( "upload_size" ) )
168+ assert_equal ( request_headers . fetch ( "X-Expected-Body-Checksum" ) , data . fetch ( "upload_checksum" ) )
169+ end
170+ end
171+
172+ assert_equal ( 3 , above_max_body_size_requests . length )
173+ above_max_body_size_requests . each do |method , method_requests |
174+ assert_equal ( 5 , method_requests . length )
175+ method_requests . each do |request |
176+ assert_response_code ( ( request . response . code == 502 ) ? 502 : 413 , request . response )
177+ assert_equal ( "text/html" , request . response . headers [ "content-type" ] )
178+ end
179+ end
180+ end
31181end
0 commit comments