Skip to content

Quoted boundary in multipart/form-data Content-Type header fails #4566

@bart-vmware

Description

@bart-vmware

When the boundary parameter in the Content-Type HTTP header field is surrounded by double quotes, the request is rejected by the server with error 500. As explained at https://developers.de/blogs/damir_dobric/archive/2013/09/10/problems-with-webapi-multipart-content-upload-and-boundary-quot-quotes.aspx, doing so is permitted according to the RFCs. The example request below originates from HttpClient, which is part of the .NET libraries. HttpClient always puts quotes around the boundary parameter, despite the presence or absence of special characters.

While it is possible to use custom code to manually patch up the request, this prevents us from using auto-generated client libraries based on an OpenAPI spec file.

Note that the double quotes are only present in the Content-Type HTTP header. The boundary value itself is unquoted.

POST https://api.example.com/v3/packages/e2c923a3-26d8-449a-acef-201052915e7f/upload HTTP/1.1
Host: api.example.com
Authorization: Bearer XXX
Content-Type: multipart/form-data; boundary="a63df4c1-ad7c-4c18-b393-1cf5d2fccca4"
Content-Length: 3791

--a63df4c1-ad7c-4c18-b393-1cf5d2fccca4
Content-Type: application/octet-stream
Content-Disposition: form-data; name="bits"; filename="PushTestApp.zip"
Content-Length: 3540

***BINARY DATA***
--a63df4c1-ad7c-4c18-b393-1cf5d2fccca4--
HTTP/1.1 500 Internal Server Error
Content-Length: 3764
Date: Tue, 16 Sep 2025 08:40:50 GMT
X-Vcap-Request-Id: 872edcc8-6a9a-4626-66cf-e051fc7e9e22

Puma caught this error: EOFError (EOFError)
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart/parser.rb:379:in `handle_empty_content!'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart/parser.rb:200:in `on_read'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart/parser.rb:80:in `block in parse'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart/parser.rb:78:in `loop'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart/parser.rb:78:in `parse'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/multipart.rb:53:in `extract_multipart'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/request.rb:594:in `parse_multipart'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/request.rb:446:in `POST'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/request.rb:469:in `params'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/request.rb:32:in `params'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/cloud_controller_ng/middleware/security_context_setter.rb:25:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/cloud_controller_ng/middleware/vcap_request_id.rb:16:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/cloud_controller_ng/middleware/cors.rb:49:in `call_app'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/cloud_controller_ng/middleware/cors.rb:14:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/cloud_controller_ng/middleware/request_metrics.rb:13:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/rack-2.2.17/lib/rack/builder.rb:244:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/configuration.rb:279:in `call'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/request.rb:99:in `block in handle_request'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/thread_pool.rb:390:in `with_force_shutdown'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/request.rb:98:in `handle_request'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/server.rb:472:in `process_client'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/server.rb:254:in `block in run'
/var/vcap/data/packages/cloud_controller_ng/a08c36364d87437dbf604055a85adfc356219952/gem_home/ruby/3.2.0/gems/puma-6.6.1/lib/puma/thread_pool.rb:167:in `block in spawn_thread'

While the suggested workaround described in the linked article works, it's not reasonable to expect auto-generated client libraries to perform similar hacks. So please adapt the server to allow a boundary parameter value between double quotes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions