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

fix: handle http response code 307 - temporary redirect #571

Merged
merged 2 commits into from Jun 25, 2017

Conversation

balamurugana
Copy link
Member

@balamurugana balamurugana commented May 5, 2017

Previously the SDK throws below exception when it gets response code 307.

java.io.EOFException: input contained no data
        at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:3003)
        at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046)
        at org.xmlpull.mxp1.MXParser.parseProlog(MXParser.java:1410)
        at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1395)
        at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093)
        at com.google.api.client.xml.Xml.parseElementInternal(Xml.java:245)
        at com.google.api.client.xml.Xml.parseElement(Xml.java:222)
        at io.minio.messages.XmlEntity.parseXml(XmlEntity.java:75)
        at io.minio.messages.ErrorResponse.parseXml(ErrorResponse.java:159)
        at io.minio.messages.ErrorResponse.<init>(ErrorResponse.java:64)
        at io.minio.MinioClient.execute(MinioClient.java:970)
        at io.minio.MinioClient.executePut(MinioClient.java:1197)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2597)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2554)
        at FunctionalTest.makeBucket_test1(FunctionalTest.java:86)
        at FunctionalTest.runTests(FunctionalTest.java:1264)
        at FunctionalTest.main(FunctionalTest.java:1380)

This patch handles response code and returns Amazon S3 error.

Copy link
Member

@vadmeste vadmeste left a comment

Choose a reason for hiding this comment

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

LGTM

@balamurugana
Copy link
Member Author

balamurugana commented May 11, 2017

I would like get 307 is handled to redirect to received location or error out. Till then 👎

// Handle 307 (temporary redirect) specially.
String location = response.headers().get("Location");
if (location == null || location.isEmpty()) {
throw new InternalException("unexpected empty value in location header");
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, this is a server issue, not internal to the SDK. Is InternalException justified here?

Copy link
Contributor

@nitisht nitisht May 31, 2017

Choose a reason for hiding this comment

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

IMO, this is a server issue, not internal to the SDK. Is InternalException justified here?

@balamurugana your views on this?

Response response = null;

// Loop to retry with new location of 307.
for (int i = 0; i < TEMP_REDIRECT_TRY_COUNT; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of doing all the process in the loop, may be it is better to get in the loop only when 307 is received? IMO that will be more readable.

Copy link
Member Author

Choose a reason for hiding this comment

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

The loop is continued only for 307. What is all the process in the loop?

My suggestion to 307 is that SDK should error out instead of retrying its own. Auto-retry doesn't solve real problem ie put object doesn't work (not only for minio-java).

Minio server returns 307 only for http to https. https would invite other problems like ignoring self signed certificate.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, I assumed request could be made outside the for loop but that is not right. This is fine.

@harshavardhana
Copy link
Member

@nitisht anything pending here for you review?

@nitisht
Copy link
Contributor

nitisht commented May 16, 2017

@harshavardhana just one comment, other than that LGTM

@balamurugana
Copy link
Member Author

@harshavardhana there are issues handling 307 for all the cases (in all the libraries). Amazon AWS S3 sends 307 and new location for temporary resource change, however in minio server, it is used as http to https redirect. However put/post ReST calls in all SDKs do not work in minio server.

Assume the case of http to https redirection using 307 where https uses self signed certificate, automatic retry on 307 would lead to certificate error. This may be a surprise error for the consumer as he was trying with http.

This needs to be discussed and taken forward accordingly.

@harshavardhana
Copy link
Member

Assume the case of http to https redirection using 307 where https uses self signed certificate, automatic retry on 307 would lead to certificate error. This may be a surprise error for the consumer as he was trying with http.

mc ls works fine btw.

mc config host add play-http http://play.minio.io:9000 Q3AM3UQ867SPQQA43P2F zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
mc ls play-http

Here is how the redirection happens

$ mc ls --debug play-http
mc: <DEBUG> GET / HTTP/1.1
Host: play.minio.io:9000
User-Agent: Minio (linux; amd64) minio-go/2.0.4 mc/2017-05-14T07:14:06Z
Authorization: AWS4-HMAC-SHA256 Credential=**REDACTED**/20170516/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=**REDACTED**
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Amz-Date: 20170516T063123Z
Accept-Encoding: gzip

mc: <DEBUG> HTTP/1.1 307 Temporary Redirect
Content-Length: 63
Content-Type: text/html; charset=utf-8
Date: Tue, 16 May 2017 06:31:33 GMT
Location: https://play.minio.io:9000/

<a href="https://play.minio.io:9000/">Temporary Redirect</a>.

mc: <DEBUG> Response Time:  47.945222ms

mc: <DEBUG> GET / HTTP/1.1
Host: play.minio.io:9000
User-Agent: Minio (linux; amd64) minio-go/2.0.4 mc/2017-05-14T07:14:06Z
Authorization: AWS4-HMAC-SHA256 Credential=**REDACTED**/20170516/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=**REDACTED**
Referer: http://play.minio.io:9000/
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Amz-Date: 20170516T063123Z
Accept-Encoding: gzip

mc: <DEBUG> HTTP/1.1 200 OK
Transfer-Encoding: chunked
Accept-Ranges: bytes
Content-Type: application/xml
Date: Tue, 16 May 2017 06:31:33 GMT
Server: Minio/DEVELOPMENT.2017-05-05T03-22-47Z (linux; amd64)
Vary: Origin
X-Amz-Bucket-Region: us-east-1
X-Amz-Request-Id: 14BF0272ED46B4F8

mc: <DEBUG> Response Time:  250.239354ms

mc: <DEBUG> GET / HTTP/1.1
Host: play.minio.io:9000
User-Agent: Minio (linux; amd64) minio-go/2.0.4 mc/2017-05-14T07:14:06Z
Authorization: AWS4-HMAC-SHA256 Credential=**REDACTED**/20170516/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=**REDACTED**
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Amz-Date: 20170516T063124Z
Accept-Encoding: gzip

mc: <DEBUG> HTTP/1.1 307 Temporary Redirect
Content-Length: 63
Content-Type: text/html; charset=utf-8
Date: Tue, 16 May 2017 06:31:33 GMT
Location: https://play.minio.io:9000/

<a href="https://play.minio.io:9000/">Temporary Redirect</a>.

mc: <DEBUG> Response Time:  13.791017ms

mc: <DEBUG> GET / HTTP/1.1
Host: play.minio.io:9000
User-Agent: Minio (linux; amd64) minio-go/2.0.4 mc/2017-05-14T07:14:06Z
Authorization: AWS4-HMAC-SHA256 Credential=**REDACTED**/20170516/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=**REDACTED**
Referer: http://play.minio.io:9000/
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Amz-Date: 20170516T063124Z
Accept-Encoding: gzip

mc: <DEBUG> HTTP/1.1 200 OK
Transfer-Encoding: chunked
Accept-Ranges: bytes
Content-Type: application/xml
Date: Tue, 16 May 2017 06:31:34 GMT
Server: Minio/DEVELOPMENT.2017-05-05T03-22-47Z (linux; amd64)
Vary: Origin
X-Amz-Bucket-Region: us-east-1
X-Amz-Request-Id: 14BF0272F0E3BA00

mc: <DEBUG> Response Time:  26.234454ms

Are you saying something else?

@harshavardhana
Copy link
Member

You are right mc cp fails. We need to fix this, there i think is a known Go bug in not having PUT redirects, PUT is automatically converted to GET after a 307 because of HTTP RFC. Need to read on why this happens.

// cc @vadmeste can you comment?

@vadmeste
Copy link
Member

i think is a known Go bug in not having PUT redirects, PUT is automatically converted to GET after a 307 because of HTTP RFC

Yes, right. But this bug is already fixed in go1.8. I already compiled mc with go1.8 and it works fine.

@balamurugana, did you test enabling automatic redirect in the http library ?

@balamurugana
Copy link
Member Author

@vadmeste

@balamurugana, did you test enabling automatic redirect in the http library ?

Do you mean golang http library or okhttp?

@vadmeste
Copy link
Member

Do you mean golang http library or okhttp?

okhttp.

I mean I wonder what's the default behavior of okhttp when it receives 307 redirect.

@balamurugana
Copy link
Member Author

I mean I wonder what's the default behavior of okhttp when it receives 307 redirect.

307 is not handled in OkHttp. Its consumer's responsibility.

@harshavardhana
Copy link
Member

@balamurugana this requires a rebase..

// Handle 307 (temporary redirect) specially.
String location = response.headers().get("Location");
if (location == null || location.isEmpty()) {
throw new InternalException("unexpected empty value in location header");
Copy link
Contributor

@nitisht nitisht May 31, 2017

Choose a reason for hiding this comment

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

IMO, this is a server issue, not internal to the SDK. Is InternalException justified here?

@balamurugana your views on this?

@harshavardhana
Copy link
Member

@balamurugana can you rebase the PR?

Previously the SDK throws below exception

```
java.io.EOFException: input contained no data
        at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:3003)
        at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046)
        at org.xmlpull.mxp1.MXParser.parseProlog(MXParser.java:1410)
        at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1395)
        at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093)
        at com.google.api.client.xml.Xml.parseElementInternal(Xml.java:245)
        at com.google.api.client.xml.Xml.parseElement(Xml.java:222)
        at io.minio.messages.XmlEntity.parseXml(XmlEntity.java:75)
        at io.minio.messages.ErrorResponse.parseXml(ErrorResponse.java:159)
        at io.minio.messages.ErrorResponse.<init>(ErrorResponse.java:64)
        at io.minio.MinioClient.execute(MinioClient.java:970)
        at io.minio.MinioClient.executePut(MinioClient.java:1197)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2597)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2554)
        at FunctionalTest.makeBucket_test1(FunctionalTest.java:86)
        at FunctionalTest.runTests(FunctionalTest.java:1264)
        at FunctionalTest.main(FunctionalTest.java:1380)
```
when it gets response code 307. This patch handles followup location
provided in server response upto 21 times like Firefox, Chrome and
OkHttp.
Previously the SDK throws below exception when it gets response code 307.

```
java.io.EOFException: input contained no data
        at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:3003)
        at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046)
        at org.xmlpull.mxp1.MXParser.parseProlog(MXParser.java:1410)
        at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1395)
        at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093)
        at com.google.api.client.xml.Xml.parseElementInternal(Xml.java:245)
        at com.google.api.client.xml.Xml.parseElement(Xml.java:222)
        at io.minio.messages.XmlEntity.parseXml(XmlEntity.java:75)
        at io.minio.messages.ErrorResponse.parseXml(ErrorResponse.java:159)
        at io.minio.messages.ErrorResponse.<init>(ErrorResponse.java:64)
        at io.minio.MinioClient.execute(MinioClient.java:970)
        at io.minio.MinioClient.executePut(MinioClient.java:1197)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2597)
        at io.minio.MinioClient.makeBucket(MinioClient.java:2554)
        at FunctionalTest.makeBucket_test1(FunctionalTest.java:86)
        at FunctionalTest.runTests(FunctionalTest.java:1264)
        at FunctionalTest.main(FunctionalTest.java:1380)
```

This patch handles response code and returns Amazon S3 error.
@balamurugana
Copy link
Member Author

Please note that this PR returns "Redirect" amazon S3 error, not following new location automatically.

@harshavardhana
Copy link
Member

What is going on with this PR? @nitisht @balamurugana @vadmeste ?

@balamurugana
Copy link
Member Author

@harshavardhana waiting on @nitisht's review

Copy link
Contributor

@nitisht nitisht left a comment

Choose a reason for hiding this comment

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

I understand it was decided to just respond with ErrorCode.REDIRECT instead of actually redirecting. LGTM in that case

@harshavardhana harshavardhana merged commit 423621d into minio:master Jun 25, 2017
@balamurugana balamurugana deleted the handle-307-code branch June 25, 2017 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants