From 5a1ae862a7bc9d7a4a81c5398fd277f5ff84b05e Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 8 Aug 2018 23:39:47 +0100 Subject: [PATCH] Avoid sending an error after 206 HTTP code (#6264) When a S3 client sends a GET Object with a range header, 206 http code is returned indicating success, however the call of the object layer's GetObject() inside the handler can return an error and will lead to writing an XML error message, which is obviously wrong since we already sent 206 http code. So in the case, we just stop sending data to the S3 client, this latter can still detect if there is no error when comparing received data with Content-Length header in the Get Object response. --- cmd/api-headers.go | 1 - cmd/object-handlers.go | 13 ++++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cmd/api-headers.go b/cmd/api-headers.go index ac030c4e6..1ed996d86 100644 --- a/cmd/api-headers.go +++ b/cmd/api-headers.go @@ -100,6 +100,5 @@ func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, contentRange *h // Override content-length w.Header().Set("Content-Length", strconv.FormatInt(contentRange.getLength(), 10)) w.Header().Set("Content-Range", contentRange.String()) - w.WriteHeader(http.StatusPartialContent) } } diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 8274841d8..87d60ccfe 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -173,16 +173,23 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req setObjectHeaders(w, objInfo, hrange) setHeadGetRespHeaders(w, r.URL.Query()) - httpWriter := ioutil.WriteOnClose(writer) getObject := objectAPI.GetObject if api.CacheAPI() != nil && !hasSSECustomerHeader(r.Header) { getObject = api.CacheAPI().GetObject } + statusCodeWritten := false + httpWriter := ioutil.WriteOnClose(writer) + + if hrange != nil && hrange.offsetBegin > -1 { + statusCodeWritten = true + w.WriteHeader(http.StatusPartialContent) + } + // Reads the object at startOffset and writes to mw. if err = getObject(ctx, bucket, object, startOffset, length, httpWriter, objInfo.ETag); err != nil { - if !httpWriter.HasWritten() { // write error response only if no data has been written to client yet + if !httpWriter.HasWritten() && !statusCodeWritten { // write error response only if no data or headers has been written to client yet writeErrorResponse(w, toAPIErrorCode(err), r.URL) } httpWriter.Close() @@ -190,7 +197,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req } if err = httpWriter.Close(); err != nil { - if !httpWriter.HasWritten() { // write error response only if no data has been written to client yet + if !httpWriter.HasWritten() && !statusCodeWritten { // write error response only if no data or headers has been written to client yet writeErrorResponse(w, toAPIErrorCode(err), r.URL) return }