-
-
Notifications
You must be signed in to change notification settings - Fork 159
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
Improve BaseHTTPClient #875
Conversation
77adbc2
to
06c54c1
Compare
06c54c1
to
c1a3f40
Compare
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.
This will be really nice to use in tests. I had some code nitpicks, but other than that I think it's great.
# Set headers for requests | ||
# | ||
# ``` | ||
# # `content_type` will be normalized to `content-type` |
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 you're trying to say:
# # `content_type` will be normalized to `content-type` | |
# # `content_type` will be normalized to `Content-Type` |
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.
Actually, I can't find this anywhere. Where does this happen? I see that headers have upcase
called on them but I don't understand how _
-> -
.
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.
Headers are case insensitive! https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive So technically it does not capitalize them, but it does change the underscore to a hyphen. That's done by Crystal :D
Should I add a note that headers are case insensitive to the docs?
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.
However it doesn't appear to change the underscore to a hyphen when setting (it does when getting the header value or the test would fail):
HTTP::Headers{"Foo" => "bar",
"accept" => "text/csv",
"accept-encoding" => "gzip, deflate",
"content-length" => "2",
"content_type" => "application/json",
"host" => "localhost:6226",
"user-agent" => "Crystal"}
I think most implementations of header parsers convert underscore to hyphen (like Crystal's does) but I think we should do it before setting just in case :)
spec/lucky/base_http_client_spec.cr
Outdated
request = server.last_request | ||
request.path.should eq "/hello" | ||
request.method.should eq("POST") | ||
request.body.not_nil!.gets_to_end.should eq(NamedTuple.new.to_json) |
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.
This caught my eye. As far as I can tell we're not sending anything as the post body. Is an empty post body somehow initialized to the json of a NamedTuple
?
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.
Now I see it down in the code with **params
. Maybe it would be worth giving that param a type or a default so we didn't have to call not_nil!
on it. It'd be cool if we could get rid of gets_to_end
also, but I don't think that's as simple. Thoughts also on changing NamedTuple.new.to_json
to "{}"
?
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 request
is an HTTP::Request
from Crystal so I can't easily change that without monkey patching it. Since end users won't be checking the request body I don't think it is worth monkey patching it.
I do like the idea about just using a string! That's a lot clearer
spec/lucky/base_http_client_spec.cr
Outdated
{% end %} | ||
end | ||
|
||
private def with_fake_server(path : String, response_body : String) | ||
TestServer.route(path: path, response_body: response_body) | ||
Lucky::Server.temp_config(host: "localhost", port: 6226) do |
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.
Any reason behind the 6226
port? Could we name it in a constant? Does it need to be configurable?
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.
Extracted a private method. It's the port of the test server
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 the reviews! I think I addressed everything
spec/lucky/base_http_client_spec.cr
Outdated
request = server.last_request | ||
request.path.should eq "/hello" | ||
request.method.should eq("POST") | ||
request.body.not_nil!.gets_to_end.should eq(NamedTuple.new.to_json) |
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 request
is an HTTP::Request
from Crystal so I can't easily change that without monkey patching it. Since end users won't be checking the request body I don't think it is worth monkey patching it.
I do like the idea about just using a string! That's a lot clearer
spec/lucky/base_http_client_spec.cr
Outdated
{% end %} | ||
end | ||
|
||
private def with_fake_server(path : String, response_body : String) | ||
TestServer.route(path: path, response_body: response_body) | ||
Lucky::Server.temp_config(host: "localhost", port: 6226) do |
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.
Extracted a private method. It's the port of the test server
# Set headers for requests | ||
# | ||
# ``` | ||
# # `content_type` will be normalized to `content-type` |
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.
Headers are case insensitive! https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive So technically it does not capitalize them, but it does change the underscore to a hyphen. That's done by Crystal :D
Should I add a note that headers are case insensitive to the docs?
# Set headers for requests | ||
# | ||
# ``` | ||
# # `content_type` will be normalized to `content-type` |
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.
However it doesn't appear to change the underscore to a hyphen when setting (it does when getting the header value or the test would fail):
HTTP::Headers{"Foo" => "bar",
"accept" => "text/csv",
"accept-encoding" => "gzip, deflate",
"content-length" => "2",
"content_type" => "application/json",
"host" => "localhost:6226",
"user-agent" => "Crystal"}
I think most implementations of header parsers convert underscore to hyphen (like Crystal's does) but I think we should do it before setting just in case :)
src/lucky/base_http_client.cr
Outdated
@client.before_request do |request| | ||
header_values = header_values | ||
.to_h | ||
.transform_keys(&.gsub("_", "_")) |
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.
Did you mean
.transform_keys(&.gsub("_", "_")) | |
.transform_keys(&.gsub("_", "-")) |
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 :D And I had to tweak this a bit because there was a compile error
c611181
to
7e6185c
Compare
Now I think it's good to go 🤣 |
This can be used for request specs. This will be used for the default auth specs when generating an API app with Auth.
I imagine this could be used for other HTTP Clients as well, but for now the main purpose is for testing Lucky apps