|
290 | 290 | req.POST.should.equal "foo" => "bar", "quux" => "bla" |
291 | 291 | end |
292 | 292 |
|
| 293 | + should "limit POST body read to bytesize_limit when parsing url-encoded data" do |
| 294 | + # Create a mock input that tracks read calls |
| 295 | + reads = [] |
| 296 | + mock_input = Object.new |
| 297 | + mock_input.define_singleton_method(:read) do |len=nil| |
| 298 | + reads << len |
| 299 | + # Return mutable string |
| 300 | + "foo=bar".dup |
| 301 | + end |
| 302 | + mock_input.define_singleton_method(:rewind) do |
| 303 | + # no-op for compatibility |
| 304 | + end |
| 305 | + |
| 306 | + request = Rack::Request.new \ |
| 307 | + Rack::MockRequest.env_for("/", |
| 308 | + 'REQUEST_METHOD' => 'POST', |
| 309 | + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', |
| 310 | + :input => mock_input) |
| 311 | + |
| 312 | + request.POST.should.equal "foo" => "bar" |
| 313 | + |
| 314 | + # Verify read was called with a limit (bytesize_limit + 2), not nil |
| 315 | + reads.size.should.equal 1 |
| 316 | + reads.first.should.not.be.nil |
| 317 | + reads.first.should.equal(Rack::Utils.bytesize_limit + 2) |
| 318 | + end |
| 319 | + |
| 320 | + should "handle nil return from rack.input.read when parsing url-encoded data" do |
| 321 | + # Simulate an input that returns nil on read |
| 322 | + mock_input = Object.new |
| 323 | + mock_input.define_singleton_method(:read) do |len=nil| |
| 324 | + nil |
| 325 | + end |
| 326 | + mock_input.define_singleton_method(:rewind) do |
| 327 | + # no-op for compatibility |
| 328 | + end |
| 329 | + |
| 330 | + request = Rack::Request.new \ |
| 331 | + Rack::MockRequest.env_for("/", |
| 332 | + 'REQUEST_METHOD' => 'POST', |
| 333 | + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', |
| 334 | + :input => mock_input) |
| 335 | + |
| 336 | + # Should handle nil gracefully and return empty hash |
| 337 | + request.POST.should.equal({}) |
| 338 | + end |
| 339 | + |
| 340 | + should "truncate POST body at bytesize_limit when parsing url-encoded data" do |
| 341 | + # Create input larger than limit |
| 342 | + large_body = "a=1&" * 1000000 # Very large body |
| 343 | + |
| 344 | + request = Rack::Request.new \ |
| 345 | + Rack::MockRequest.env_for("/", |
| 346 | + 'REQUEST_METHOD' => 'POST', |
| 347 | + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', |
| 348 | + :input => large_body) |
| 349 | + |
| 350 | + # Should parse only up to the limit without reading entire body into memory |
| 351 | + # The actual parsing may fail due to size limit, which is expected |
| 352 | + proc { request.POST }.should.raise Rack::Utils::QueryLimitError |
| 353 | + end |
| 354 | + |
| 355 | + should "clean up Safari's ajax POST body with limited read" do |
| 356 | + # Verify Safari null-byte cleanup still works with bounded read |
| 357 | + reads = [] |
| 358 | + mock_input = Object.new |
| 359 | + mock_input.define_singleton_method(:read) do |len=nil| |
| 360 | + reads << len |
| 361 | + # Return mutable string (dup ensures it's not frozen) |
| 362 | + "foo=bar\0".dup |
| 363 | + end |
| 364 | + mock_input.define_singleton_method(:rewind) do |
| 365 | + # no-op for compatibility |
| 366 | + end |
| 367 | + |
| 368 | + request = Rack::Request.new \ |
| 369 | + Rack::MockRequest.env_for("/", |
| 370 | + 'REQUEST_METHOD' => 'POST', |
| 371 | + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', |
| 372 | + :input => mock_input) |
| 373 | + |
| 374 | + request.POST.should.equal "foo" => "bar" |
| 375 | + |
| 376 | + # Verify bounded read was used |
| 377 | + reads.first.should.not.be.nil |
| 378 | + end |
| 379 | + |
293 | 380 | should "get value by key from params with #[]" do |
294 | 381 | req = Rack::Request.new \ |
295 | 382 | Rack::MockRequest.env_for("?foo=quux") |
|
0 commit comments