This adds more tests to `curl_spec.rb` to increase test coverage.
This brings almost all of the methods that don't make network
requests up to 100% line and branch coverage (the exception being
some guards in `parse_curl_output` that shouldn't happen under
normal circumstances).
In the process of writing more tests for `parse_curl_response`, I
made some tweaks to remove checks for conditions that shouldn't ever
be true (e.g., `match["code"]` isn't optional, so it will be present
if `HTTP_STATUS_LINE_REGEX` matches) and to refactor some others. I
contributed this method a while back (9171eb2), so this is me coming
back to clarify some behavior.
- Some casks have URL arguments like "referer" (spelled wrong, that's
intentional in the HTTP spec).
- The audit for one such cask, `iThoughtsX`, was failing because the
"referer" wasn't getting passed through to cURL so the access would
404.
----
Before:
```
❯ brew audit --cask --online --appcast --signing 'ithoughtsx'
[...]
audit for ithoughtsx: failed
- The binary URL https://cdn.toketaware.com?download=iThoughtsX.zip is not reachable (HTTP status code 404)
- Version '9.2.0' differs from '9.3.0' retrieved by livecheck.
- Version '9.2.0' differs from '9.3.0' retrieved by livecheck.
Error: 2 problems in 1 cask detected
```
After:
```
❯ brew audit --cask --online --appcast --signing 'ithoughtsx'
[...]
audit for ithoughtsx: failed
- Version '9.2.0' differs from '9.3.0' retrieved by livecheck.
- Version '9.2.0' differs from '9.3.0' retrieved by livecheck.
Error: 1 problem in 1 cask detected
```
Update base URL when there is an absolute location, so that following
relative locations are considered relative to the new base.
Consider below cURL output for https://example_one.com:
HTTP/1.1 302 Moved Temporarily
Location: https://example_two.com
HTTP/1.1 302 Moved Temporarily
Location: /foo/
HTTP/1.1 200 OK
The final URL should be https://example_two.com/foo/ rather than
https://example_one.com/foo/.
The return hash from `#curl_http_content_headers_and_checksum`
contains a `:status`, which is the status code of the last response.
This string value comes from `#parse_curl_response`, where the key is
`:status_code` instead.
Aligning these keys technically allows us to pass either of these
hashes to the `#url_protected_by_*` methods, as both contain
`:status_code` and `:headers` in the expected format.
Before `#parse_curl_output` was introduced and related methods were
updated to use it, `#url_protected_by_cloudflare?` and
`#url_protected_by_incapsula?` were checking a string of all the
headers from a response and using a regex to check related header
values.
However, when `#curl_http_content_headers_and_checksum` was updated
to use `#parse_curl_output` internally, the `:headers` value became
a hash generated by `#parse_curl_response`. The `#url_protected_by_*`
methods were updated to work with the hash value but this wasn't able
to fully replicate the previous behavior because
`#parse_curl_response` was only keeping the last instance of a given
header (maintaining pre-existing behavior). This is an issue for
these methods because they check `Set-Cookie` headers and there can
be multiple instances of this header in a response.
This commit updates these methods to handle an array of strings in
addition to the existing string support. This change ensures that
these methods properly check all `Set-Cookie` headers, effectively
reinstating the previous behavior.
Past that, this updates one of the early return values in
`#url_protected_by_cloudflare?` to be `false` instead of an implicit
`nil`. After adding a type signature to this method, it became clear
that it wasn't always returning a boolean value and this fixes it.
`Curl#parse_curl_response` only includes the last instance of a given
header in its `:headers` hash (replicating pre-existing behavior).
This is a problem for headers like `Set-Cookie`, which can appear more
than once in a response.
This commit addresses the issue by collecting duplicate headers into
an array instead. Headers that only appear once in the response will
still have a string value but headers that appear more than once will
be an array of strings. Whenever headers from `#parse_curl_response`
are used (directly or indirectly), it's important to conditionally
handle the expected types.