-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Don't print query params if they are empty #5340
Conversation
src/uri.cr
Outdated
@@ -128,7 +128,7 @@ class URI | |||
def full_path | |||
String.build do |str| | |||
str << (@path.try { |p| !p.empty? } ? @path : "/") | |||
str << "?" << @query if @query | |||
str << "?" << @query if @query && @query != "" |
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.
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.
Good idea!
121c070
to
997baf9
Compare
src/uri.cr
Outdated
@@ -128,7 +128,7 @@ class URI | |||
def full_path | |||
String.build do |str| | |||
str << (@path.try { |p| !p.empty? } ? @path : "/") | |||
str << "?" << @query if @query | |||
str << "?" << @query if @query && [email protected](&.empty?) |
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.
Better: if (query = @query) && !query.empty?
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 like that 👍
997baf9
to
326aa17
Compare
src/uri.cr
Outdated
@@ -128,7 +128,7 @@ class URI | |||
def full_path | |||
String.build do |str| | |||
str << (@path.try { |p| !p.empty? } ? @path : "/") | |||
str << "?" << @query if @query | |||
str << "?" << @query if (query = @query) && !query.empty? |
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 would personally prefer move the assign and condition to the left side (a regular if
)
if (query = @query) && !query.empty?
str << "?" << query
end
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.
You should probably replace this with the following which is much clearer as to your intent.
str << "?" << @query if !@query.to_s.empty?
More importantly since @query
is literally the same thing as query
owing to the getter
setting it to itself is just weird. I wanted to see if there was some dark magic I was ignorant of, but as far as i can tell this assignment makes no sense.
class Foo
getter x
setter x
def initialize(@x : String?)
end
def test : Bool
(x = @x) ? true : false
end
def test2 : Bool
x ? true : false
end
def test3 : Bool
@x ? true : false
end
end
then checking it in icr...
icr(0.23.1) > f = Foo.new("something")
=> #<Foo:0x107231e60 @x="something">
icr(0.23.1) > f.test
=> true
icr(0.23.1) > f.test2
=> true
icr(0.23.1) > f.test3
=> true
icr(0.23.1) > f = Foo.new(nil)
=> #<Foo:0x1070c8e40 @x=nil>
icr(0.23.1) > f.test
=> false
icr(0.23.1) > f.test2
=> false
icr(0.23.1) > f.test3
=> false
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.
@masukomi Thanks for the feedback and the detailed response. That example is not quite right for showing the problem. Here's one that illustrates the issue: https://play.crystal-lang.org/#/r/36hx
class Foo
@query : String?
def full_path
String.build do |str|
str << @query if @query && @query.empty?
end
end
end
Foo.new.full_path
Results in:
in line 6: undefined method 'empty?' for Nil (compile-time type is (String | Nil))
I wish I could find the documentation for this, but the gist is that instance variable can change at any time so you need to set it to a local variable first so the compiler can be sure that it is still not nil. Does that make sense?
[email protected]_s.empty?
would work, but it requires making an intermediate string object if the query is nil
, which IMO is not worth it for slightly improved readability
src/uri.cr
Outdated
@@ -128,7 +128,7 @@ class URI | |||
def full_path | |||
String.build do |str| | |||
str << (@path.try { |p| !p.empty? } ? @path : "/") | |||
str << "?" << @query if @query | |||
str << "?" << @query if (query = @query) && !query.empty? |
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.
You should probably replace this with the following which is much clearer as to your intent.
str << "?" << @query if !@query.to_s.empty?
More importantly since @query
is literally the same thing as query
owing to the getter
setting it to itself is just weird. I wanted to see if there was some dark magic I was ignorant of, but as far as i can tell this assignment makes no sense.
class Foo
getter x
setter x
def initialize(@x : String?)
end
def test : Bool
(x = @x) ? true : false
end
def test2 : Bool
x ? true : false
end
def test3 : Bool
@x ? true : false
end
end
then checking it in icr...
icr(0.23.1) > f = Foo.new("something")
=> #<Foo:0x107231e60 @x="something">
icr(0.23.1) > f.test
=> true
icr(0.23.1) > f.test2
=> true
icr(0.23.1) > f.test3
=> true
icr(0.23.1) > f = Foo.new(nil)
=> #<Foo:0x1070c8e40 @x=nil>
icr(0.23.1) > f.test
=> false
icr(0.23.1) > f.test2
=> false
icr(0.23.1) > f.test3
=> false
326aa17
to
b50d7a3
Compare
src/uri.cr
Outdated
@@ -128,7 +128,7 @@ class URI | |||
def full_path | |||
String.build do |str| | |||
str << (@path.try { |p| !p.empty? } ? @path : "/") | |||
str << "?" << @query if @query | |||
str << "?" << @query unless @query.try(&.empty?) |
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 this is pretty clean and eliminates the need to create an intermediate variable. I think this is a pretty small change, is reasonably easy to understand, and is unlikely to change much in the future. So it's probably ok like this. However, if it needs to change to change to be merged in, I'm happy to change it!
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 won't work: if @query
is nil
, @query.try(&.empty?)
will return nil
which is falsey and thus add a question mark. You need add a spec for this case.
And I still think my previous proposal (query = @query) && !query.empty?
is probably the best boolean expression for this, but maybe put it in a proper if
branch to spare an additional ivar lookup:
if (query = @query) && !query.empty?
str << '?' << query
end
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 please
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 I noticed this didn't work and updated it last night. Did you see the latest change using try
https://github.com/crystal-lang/crystal/pull/5340/files? I think it is easier to understand, but maybe that's just me. @RX14 if you'd still prefer assigning to the intermediate variable instead of the try
that I used, LMK and I'll change it.
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 personally think if
branching is easier to understand over a .try
block, but performance wise, a try
block might show better performance than if
branch.
https://gist.github.com/luislavena/4096693021ca38f6be4c7539625716a3
The difference might be marginal, so leave that decision to core in relation to readability/simplicity vs performance.
Cheers.
4cf0442
to
c13c4f1
Compare
I found this while investigating this issue on Lucky: luckyframework/lucky#214 It turns out that because I parsed the query params in that handler it set the URI#query to `""`. This caused `HTTP::Request#resource` to add an extra `?` to the end of the path, even though the query params were empty. This PR fixes the issue by also checking for an empty string before printing `?`.
c13c4f1
to
aa3f3d4
Compare
I switched it to what @straight-shoota suggested: #5340 (comment) |
Thanks @paulcsmith ! |
I found this while investigating this issue on Lucky:
luckyframework/lucky#214
It turns out that because I parsed the query params in the handler mentioned in the above link, it
set the
URI#query
to""
. This causedHTTP::Request#resource
to addan extra
?
to the end of the path, even though the query params wereempty.
This PR fixes the issue by also checking for an empty string before
printing
?