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.
master
Anis Elleuch 6 years ago committed by Harshavardhana
parent 6df20734f9
commit 5a1ae862a7
  1. 1
      cmd/api-headers.go
  2. 13
      cmd/object-handlers.go

@ -100,6 +100,5 @@ func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, contentRange *h
// Override content-length // Override content-length
w.Header().Set("Content-Length", strconv.FormatInt(contentRange.getLength(), 10)) w.Header().Set("Content-Length", strconv.FormatInt(contentRange.getLength(), 10))
w.Header().Set("Content-Range", contentRange.String()) w.Header().Set("Content-Range", contentRange.String())
w.WriteHeader(http.StatusPartialContent)
} }
} }

@ -173,16 +173,23 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
setObjectHeaders(w, objInfo, hrange) setObjectHeaders(w, objInfo, hrange)
setHeadGetRespHeaders(w, r.URL.Query()) setHeadGetRespHeaders(w, r.URL.Query())
httpWriter := ioutil.WriteOnClose(writer)
getObject := objectAPI.GetObject getObject := objectAPI.GetObject
if api.CacheAPI() != nil && !hasSSECustomerHeader(r.Header) { if api.CacheAPI() != nil && !hasSSECustomerHeader(r.Header) {
getObject = api.CacheAPI().GetObject 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. // Reads the object at startOffset and writes to mw.
if err = getObject(ctx, bucket, object, startOffset, length, httpWriter, objInfo.ETag); err != nil { 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) writeErrorResponse(w, toAPIErrorCode(err), r.URL)
} }
httpWriter.Close() httpWriter.Close()
@ -190,7 +197,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
} }
if err = httpWriter.Close(); err != nil { 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) writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return return
} }

Loading…
Cancel
Save