Skip to content

Conversation

@seanpdoyle
Copy link
Contributor

Proposal

This commit changes the private Connection#request method to invoke Net::HTTP#request, rather than the individual verb methods (like get, post, etc.).

Since the Net::HTTP#request method expects an instance (rather than its constituent parts), this commit also changes the Connection#request method to construct an instance of the HTTP method-appropriate class:

While the behavior changes aim to be minimal, the availability of a Net::HTTP request instance enables more future pre-request modifications (for example, to support for Files through multipart/form-data requests like outlined in #394).

Additional information

Net::HTTP Request instances downcase all HTTP header names, but supports reading from values regardless of the key's casing:

request["Accept"] = "application/json"  # => "application/json"
request.each.to_h                       # => {"accept"=>"application/json"}
request["Accept"]                       # => "application/json"
request["accept"]                       # => "application/json"

Additionally, new Net::HTTP Request instances come with default headers:

accept-encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
user-agent: Ruby
host: 37s.sunrise.i:3000

The host: key is inferred from the request instance's URI.

For the sake of backwards compatibility, this commit clears all default headers prior to merging any provided or inferred headers (like content-type or accept).

@seanpdoyle seanpdoyle force-pushed the net-http-requests branch 2 times, most recently from dd3e0e9 to 3f96385 Compare October 24, 2025 17:27
payload[:request_uri] = "#{site.scheme}://#{site.host}:#{site.port}#{path}"
payload[:headers] = headers
payload[:request_uri] = request.uri.to_s
payload[:headers] = request.each.to_h
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
payload[:headers] = request.each.to_h
payload[:headers] = request.to_hash

?

Copy link
Contributor Author

@seanpdoyle seanpdoyle Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, there is a different between the value returned by Net::HTTPHeader#to_hash and Net::HTTPHeader#each_capitalized`:

request.to_hash                # => {"accept"=>["application/json"]}
request. each_capitalized.to_h # => {"accept"=>"application/json"}

Calling to_hash results in a Hash where all the values are wrapped in Arrays, whereas each_capitalized.to_h does not.

In my opinion, calling to_hash is more correct, in that Net HTTP knows how to transform multi-value headers to the underlying HTTP request.

Having said that, it probably represents a backwards incompatibile breaking change from the current behavior. We could merge this and include it in a release, and then replace each_capitalized.to_h with to_hash in a future major release. What do you think @rafaelfranca ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with current implementation. Let's keep as is

Move the `get: "Accept",` to a new line and horizontally align it with
the rest of the keys.
Proposal
---

This commit changes the private `Connection#request` method to invoke
[Net::HTTP#request][], rather than the individual verb methods (like
[get][], [post][], etc.).

Since the `Net::HTTP#request` method expects an instance (rather than
its constituent parts), this commit also changes the
`Connection#request` method to construct an instance of the HTTP
method-appropriate class:

*  `GET` builds [Net::HTTP::Get][]
*  `PUT` builds [Net::HTTP::Put][]
*  `POST` builds [Net::HTTP::Post][]
*  `PATCH` builds [Net::HTTP::Patch][]
*  `DELETE` builds [Net::HTTP::Delete][]
*  `HEAD` builds [Net::HTTP::Head][]

While the behavior changes aim to be minimal, the availability of a
Net::HTTP request instance enables more future pre-request modifications
(for example, to support for Files through `multipart/form-data`
requests like outlined in [rails#394][]).

Additional information
---

Net::HTTP Request instances downcase all HTTP header names, but supports
reading from values regardless of the key's casing:

```ruby
request["Accept"] = "application/json"  # => "application/json"
request.each.to_h                       # => {"accept"=>"application/json"}
request["Accept"]                       # => "application/json"
request["accept"]                       # => "application/json"
```

Additionally, new Net::HTTP Request instances come with default headers:

```
accept-encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
user-agent: Ruby
host: 37s.sunrise.i:3000
```

The `host:` key is inferred from the request instance's URI.

For the sake of backwards compatibility, this commit clears all default
headers prior to merging any provided or inferred headers (like
`content-type` or `accept`).

[Net::HTTP#request]: https://docs.ruby-lang.org/en/master/Net/HTTP.html#method-i-request
[get]: https://docs.ruby-lang.org/en/master/Net/HTTP.html#method-c-get
[post]: https://docs.ruby-lang.org/en/master/Net/HTTP.html#method-c-post
[Net::HTTP::Get]: https://docs.ruby-lang.org/en/master/Net/HTTP/Get.html
[Net::HTTP::Put]: https://docs.ruby-lang.org/en/master/Net/HTTP/Put.html
[Net::HTTP::Post]: https://docs.ruby-lang.org/en/master/Net/HTTP/Post.html
[Net::HTTP::Patch]: https://docs.ruby-lang.org/en/master/Net/HTTP/Patch.html
[Net::HTTP::Delete]: https://docs.ruby-lang.org/en/master/Net/HTTP/Delete.html
[Net::HTTP::Head]: https://docs.ruby-lang.org/en/master/Net/HTTP/Head.html
[rails#394]: rails#394
@rafaelfranca rafaelfranca merged commit 6dcf2d6 into rails:main Oct 27, 2025
19 checks passed
@seanpdoyle seanpdoyle deleted the net-http-requests branch October 27, 2025 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants