Skip to content
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

Adds percent-encoding for Location headers #21057

Merged
merged 1 commit into from
Dec 19, 2016

Conversation

a2lin
Copy link
Contributor

@a2lin a2lin commented Oct 21, 2016

This pr should cause unicode elements in the location header to be percent-encoded, instead of being left alone.

For the cases mentioned by @weltenwort in #21016, they now return:

curl -XPUT -v 'http://localhost:9200/someindex/sometype/%C3%A4' -d {}
< HTTP/1.1 201 Created
< Location: /someindex/sometype/%C3%A4
< content-type: application/json; charset=UTF-8
< content-length: 148
< 
curl -XPUT -v 'http://localhost:9200/someindex/sometype/%E2%9D%A4' -d '{}'
< HTTP/1.1 201 Created
< Location: /someindex/sometype/%E2%9D%A4
< content-type: application/json; charset=UTF-8
< content-length: 149
< 

The above responses compare favorably with the responses from a checkout of current master:

curl -XPUT -v 'http://localhost:9200/someindex/sometype/%C3%A4' -d {}
< HTTP/1.1 201 Created
< Location: /someindex/sometype/‰
< content-type: application/json; charset=UTF-8
< content-length: 147
< 
curl -XPUT -v 'http://localhost:9200/someindex/sometype/%E2%9D%A4' -d '{}'
< HTTP/1.1 201 Created
< Location: /someindex/sometype/?
< content-type: application/json; charset=UTF-8
< content-length: 149
< 

Closes #21016

Copy link
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a comment.

try {
URI uri = new URI(location.toString());
return uri.toASCIIString();
} catch (URISyntaxException ex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using an exception for flow control should be avoided here. Is there another way?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, when using an exception for flow control like this, it at a minimum needs to be commented to explain what is going on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fairly sure Location is supposed to be a valid URI. I'd be ok with catching the exception and logging a warning for it unless we expect this to fail frequently. If we do then we shouldn't be using URI.

try {
URI uri = new URI(location.toString());
return uri.toASCIIString();
} catch (URISyntaxException ex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fairly sure Location is supposed to be a valid URI. I'd be ok with catching the exception and logging a warning for it unless we expect this to fail frequently. If we do then we shouldn't be using URI.

@a2lin
Copy link
Contributor Author

a2lin commented Oct 22, 2016

@jasontedor, @nik9000 I've collapsed the try/catch return statements into a single return statement, commented it and added a logging statement. I don't expect the exception case to be hit at all, as the Location header should contain a valid URI.

Thanks for the comments and reviews!

locationString = uri.toASCIIString();
} catch (URISyntaxException ex) {
// could not encode URI properly, using toString instead.
logger.debug("Location string is not a valid URI.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add the exception to the log statement? If we really don't expect this to happen I think it should be a warn level. If someone is able to reproduce it then they can silence it with the update settings API before we work around it.

Now that I think about it, it'd be nicer to throw the URISyntaxException out of the method and then catch it when we go to write the location, warning there instead of here. That way we don't add the Location header with an empty string.

@a2lin a2lin force-pushed the encode_location_header branch 2 times, most recently from dd74d08 to 5dfa3a9 Compare November 10, 2016 05:54
@a2lin
Copy link
Contributor Author

a2lin commented Nov 10, 2016

@nik9000 @jasontedor I've rebased onto latest master. Returning null from this method will cause the downstream consumer to not add the 'Location' header to the response. We expect to almost never return null.

try {
URI uri = new URI(location.toString());
locationString = uri.toASCIIString();
} catch (URISyntaxException ex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was thinking that it'd be better to just throw the exception and catch it in the caller. That way the caller can log the warning and not add the location header.

@a2lin
Copy link
Contributor Author

a2lin commented Nov 11, 2016

@nik9000 I've made the change and added a test for the exception behavior.

Copy link
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @a2lin, I'm much happier with this now. I left a request for one more change.


public DocWriteResponse(ShardId shardId, String type, String id, long version, Result result) {
this.shardId = shardId;
this.type = type;
this.id = id;
this.version = version;
this.result = result;
this.logger = LogManager.getLogger(getClass());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be here. You should use ESLoggerFactory instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think this logger can be removed now (thankfully).

@@ -176,7 +182,7 @@ public RestStatus status() {
* Gets the location of the written document as a string suitable for a {@code Location} header.
* @param routing any routing used in the request. If null the location doesn't include routing information.
*/
public String getLocation(@Nullable String routing) {
public String getLocation(@Nullable String routing) throws URISyntaxException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much better.

Copy link
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked more closely, I think the logger can just go now.


public DocWriteResponse(ShardId shardId, String type, String id, long version, Result result) {
this.shardId = shardId;
this.type = type;
this.id = id;
this.version = version;
this.result = result;
this.logger = LogManager.getLogger(getClass());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think this logger can be removed now (thankfully).

@a2lin
Copy link
Contributor Author

a2lin commented Nov 14, 2016

@jasontedor Oops, sorry 'bout that. I've killed the logger.
Thanks for the catch!

@a2lin
Copy link
Contributor Author

a2lin commented Dec 14, 2016

@jasontedor @nik9000 rebased to master. Was there something else I should have fixed?

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a small thing but it looks good to me.

};
try {
invalid.getLocation(null);
fail("Did not correctly throw exception on invalid Location parameters");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use expectThrows here. I also like assertion something about the exception's massage just to make sure I caught the one I expected.

@a2lin a2lin force-pushed the encode_location_header branch from d9b8b42 to 4e64ba3 Compare December 15, 2016 05:43
@a2lin
Copy link
Contributor Author

a2lin commented Dec 15, 2016

@nik9000 Wow, did not know that expectThrows was a thing. Nifty.

@nik9000
Copy link
Member

nik9000 commented Dec 19, 2016

This looks good to me now.

elasticmachine, please test this

@nik9000 nik9000 merged commit 0ab3cbe into elastic:master Dec 19, 2016
@nik9000
Copy link
Member

nik9000 commented Dec 19, 2016

Thanks @a2lin! Sorry it took me so long to review this. I've merged to master and I'll backport to 5.x so it should go out with 5.2.

master: 0ab3cbe
5.x: 8e3d09d

nik9000 pushed a commit that referenced this pull request Dec 19, 2016
This should cause unicode elements in the location header to be percent-encoded, instead of being left alone.

Closes #21016
@a2lin
Copy link
Contributor Author

a2lin commented Dec 20, 2016

Thanks for reviewing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants