-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create separate types for request and response headers #190
Conversation
I may have misunderstood the intent of h = headers
[ Tuple "Set-Cookie" "foo=21"
, Tuple "Set-Cookie" "bar=21"
] inserts
? |
According to RFC 7230, section 3.2.2:
I'm not entirely sure of how browsers handle this exactly, but it seems like node's implementation doesn't concatenate fields with comma-separated lists and instead renders them as multiple field-value pairs, see nodejs/node#3591 and nodejs/node#14200. |
Now that `ResponseHeaders` supports multiple values per header, we can't just set the same header multiple times, but should, instead, use the `Node.HTTP.setHeaders` function. According to the [Node.js docs](https://nodejs.org/api/http.html#requestsetheadername-value), if we set a header that "[...] already exists in the to-be-sent headers, its value will be replaced."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for picking this up @arthurxavierx! I have a few questions or comments to discuss below, but overall this looks good!
src/HTTPure/RequestHeaders.purs
Outdated
read :: Request -> RequestHeaders | ||
read = requestHeaders >>> RequestHeaders |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like we're missing a way to access array-like headers like set-cookie
here. Should we also have a read'
that returns maybe a RequestHeaders' (Object (Array String))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem here is that we just can't know which headers are array-like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can with FFI. That of course requires us to assume a JS backend, but we're already using Node bindings e.g. for setHeaders
, so I think we've already made that assumption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have a function that returns Either String (Array String)
for the headers, I guess, is that what you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we have read :: Request -> Object String
, we could also have read' :: Request -> Object (Array String)
. Or we could have a more descriptive name like readArray :: Request -> Object (Array String)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, either change is breaking, it's just breaking in different directions (
Basically, instead of splitting
Headers
intoRequestHeaders
andResponseHeaders
, we'd split it intoStringHeaders
andArrayHeaders
).
If we go with the direction of this PR, it probably wouldn't be worth it to adopt my suggestion later. It's more a one or the other choice IMO.
But like I said, I don't feel strongly here. It seems a more flexible API, but maybe there's no point in supporting array headers for requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it though, my suggestion might not require a breaking change. We just add a new ArrayHeaders
type to HTTPure.Headers
, and the supporting functions. Or even add a new module for HTTPure.ArrayHeaders
(again, not set on the name, maybe MultipleHeaders
or HeadersCollection
, etc.), and then the current headers continue to work as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One major problem with this approach is that we'd also have to create HTTPure.Request.RequestArray
and HTTPure.Response.ResponseArray
variants, as currently HTTPure.Request.Request
and HTTPure.Request.Response
both have a headers :: HTTPure.Headers.Headers
field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would just extend them to contain both (I'm now thinking the name could be MultiHeaders
instead of ArrayHeaders
):
type Request =
{ method :: Method
, path :: Path
, query :: Query
, headers :: Headers
+ , multiHeaders :: MultiHeaders
, httpVersion :: Version
, url :: String
}
type Response =
{ status :: Status
, headers :: Headers
+ , multiHeaders :: MultiHeaders
, writeBody :: HTTP.Response -> Aff Unit
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm I hadn't considered that option. Looks like it should work. Thanks!
Now that we differentiate between Request and Response headers, it doesn't make sense to provide the `ResponseHeaders.empty` value as a re-export in `HTTPure`, as it could be unclear which type of headers we're talking about.
> Run nix-shell --run check-format-purescript
Some files are not formatted:
/home/runner/work/purescript-httpure/purescript-httpure/test/Test/HTTPure/RequestHeadersSpec.purs
Error: Process completed with exit code 1. Looks like there's a formatting issue in |
Closing in favor of #197. |
Closes #157. This pull request separates the
Headers
type intoRequestHeaders
andResponseHeaders
respectively, as discussed in #157 (comment).The only breakage this introduces is with module imports. The
headers
andheader
functions still work on singleton headers, but I've introducedheaders'
andheader'
respectively for setting multiple values.I could also update relevant documentation for this if needed.