(PUP-9566) Include user-specified headers in http requests#7986
Conversation
|
CLA signed by all contributors. |
8a9e637 to
02df367
Compare
02df367 to
6fc12a0
Compare
|
I realized we're not testing to ensure each different http request is including puppet headers, so I went a little overboard with the tests. I'm going to scale it back, but I figured I should at least let y'all know why this was taking so long |
6fc12a0 to
daba317
Compare
daba317 to
57b887b
Compare
|
jenkins please test with servertests |
1 similar comment
|
jenkins please test with servertests |
|
jenkins please test this with servertests |
| :http_extra_headers | ||
| end | ||
|
|
||
| def munge(headers) |
There was a problem hiding this comment.
I don't know how much we care about this, but this leaves open the possibility of a user not specifying headers correctly and not raising any errors.
For example, a user could supply a header, but no value that we can find. This will raise an error farther down the line
irb(main):016:0> [["string", "derp"], ["sadf"]].each do |name, value|
irb(main):017:1* puts name
irb(main):018:1> puts value
irb(main):019:1> headers[name] = value
irb(main):020:1> end
string
derp
TypeError: no implicit conversion of String into Integer
but it doesn't seem like a useful error at all.
irb(main):008:0> subject.munge('string')
=> [["string"]]
irb(main):009:0> subject.munge('string:derp')
=> [["string", "derp"]]
irb(main):010:0> subject.munge('string:derp,sadf:fasd')
=> [["string", "derp"], ["sadf", "fasd"]]
irb(main):011:0> subject.munge('string:derp,sadf')
=> [["string", "derp"], ["sadf"]]
Do we care? Should I make this better?
There was a problem hiding this comment.
It would be good to ensure every header has a non-empty value
There was a problem hiding this comment.
I'm validating this when we add custom headers to the headers hash rather than here
49b7f9f to
33e1a6f
Compare
| end | ||
|
|
||
| #TODO should we accept this? should we raise an error? | ||
| describe 'when given headers with no value' |
There was a problem hiding this comment.
Open question on how we want to handle this situation
There was a problem hiding this comment.
According to https://tools.ietf.org/html/rfc7230#section-3.2
header-field = field-name ":" OWS field-value OWS
field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text
So each field-value consists of one or more VCHAR (visible US-ASCII), so this case should be an error.
lib/puppet/http/service.rb
Outdated
|
|
||
| # Add additional user-defined headers if they are defined | ||
| Puppet[:http_extra_headers].each do |name, value| | ||
| if modified_headers.key?(name) |
There was a problem hiding this comment.
Since http header names are case-insensitive, you'll need to do something like the following. The number of extra headers should be fairly low, so I'm not too concerned about O(n^2)
modifies_headers.keys.find { |key| key.casecmp(name) == 0 }There was a problem hiding this comment.
I would love to add a test for add_puppet_headers tospec/unit/http/service_spec.rb, but I can't since it's a protected method. Does the benefit of having it protected outweigh being able to test the method directly? I'm mostly being lazy and not wanting to duplicate functionality tests everywhere. I'm adding a check here to raise if we have a header with an empty value
There was a problem hiding this comment.
In that case I'd define a test service subclass like class TestService < Puppet::HTTP::Service and define a method headers that calls the protected add_puppet_headers. Then in your test call TestService#headers and verify it parses/rejects headers as expected. That way you can everything in one place, instead of once per service.
There was a problem hiding this comment.
in spec/unit/http/service_spec.rb or a different file?
There was a problem hiding this comment.
yeah in service_spec.rb. We do something similar in session_spec.rb when creating the DummyResolver.
21a56fe to
5c58a83
Compare
| Puppet.warning(_('Ignoring extra header "%{name}" as it was previously set.') % { name: name }) | ||
| else | ||
| if value.nil? || value.empty? | ||
| Puppet.warning(_('Ignoring extra header "%{name}" as it has no value.') % { name: name }) |
There was a problem hiding this comment.
@joshcooper I decided rather than fail, a warning in the logs should be sufficient. I'm happy to make this a proper failure if you think it should be though
5c58a83 to
12918f7
Compare
joshcooper
left a comment
There was a problem hiding this comment.
Looks great! Travis is complaining about an unused response variable in https://github.com/puppetlabs/puppet/pull/7986/files#diff-972df990c2e008610ec5c7a5edcfebdbR14. Feel free to update and merge after CI passes
When we submit a request to the server, we now have the ability to add
in additional arbitrary headers. This should be isolated only to
requests made to a puppetserver, and these headers should not be
included in a request to an arbitrary external host.
These headers can be set with the `:http_extra_headers` setting in
Puppet. As illustrated in the various tests, this setting can be defined
in the following four forms:
- string:
`'header1:value,header2:value'`
- array:
`['header1:value', 'header2:value']`
- array of arrays:
`[['header1', 'value'], ['header2', 'value']]`
- hash:
`{'header1' => 'value', 'header2' => 'value'}`.
This commit also updates tests for the different services. It bundles
the test for the puppet profile header with the test for these custom
headers. These are both set in the same method, so a single test for
both makes sense. I also added the test for each different type of http
connection for the different services, to ensure consistent behavior
across all of them.
12918f7 to
4dbf4d5
Compare
When we submit a request to the server, we now have the ability to add
in additional arbitrary headers. This should be isolated only to
requests made to a puppetserver, and these headers should not be
included in a request to an arbitrary external host.
These headers can be set with the
:http_extra_headerssetting inPuppet. As illustrated in the various tests, this setting can be defined
in the following four forms:
'header1:value,header2:value'['header1:value', 'header2:value'][['header1', 'value'], ['header2', 'value']]{'header1' => 'value', 'header2' => 'value'}.This commit also updates tests for the different services. It bundles
the test for the puppet profile header with the test for these custom
headers. These are both set in the same method, so a single test for
both makes sense. I also added the test for each different type of http
connection for the different services, to ensure consistent behavior
across all of them.