http: Enable Transfer-Encoding chunked transfer

Fixes #1020
master
Harshavardhana 9 years ago
parent 82212f5fbc
commit 0c6a6dc380
  1. 18
      api-headers.go
  2. 18
      api-response.go
  3. 3
      appveyor.yml
  4. 44
      bucket-handlers.go
  5. 24
      object-handlers.go

@ -32,7 +32,7 @@ import (
// Static alphaNumeric table used for generating unique request ids // Static alphaNumeric table used for generating unique request ids
var alphaNumericTable = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") var alphaNumericTable = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
// generateRequestID generate request id // generateRequestID - Generate request id
func generateRequestID() []byte { func generateRequestID() []byte {
alpha := make([]byte, 16) alpha := make([]byte, 16)
rand.Read(alpha) rand.Read(alpha)
@ -43,14 +43,11 @@ func generateRequestID() []byte {
} }
// Write http common headers // Write http common headers
func setCommonHeaders(w http.ResponseWriter, contentLength int) { func setCommonHeaders(w http.ResponseWriter) {
// set unique request ID for each reply // Set unique request ID for each reply.
w.Header().Set("X-Amz-Request-Id", string(generateRequestID())) w.Header().Set("X-Amz-Request-Id", string(generateRequestID()))
w.Header().Set("Server", ("Minio/" + minioReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")")) w.Header().Set("Server", ("Minio/" + minioReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"))
w.Header().Set("Accept-Ranges", "bytes") w.Header().Set("Accept-Ranges", "bytes")
w.Header().Set("Connection", "close")
// should be set to '0' by default
w.Header().Set("Content-Length", strconv.Itoa(contentLength))
} }
// Write error response headers // Write error response headers
@ -68,12 +65,15 @@ func setObjectHeaders(w http.ResponseWriter, metadata fs.ObjectMetadata, content
// set common headers // set common headers
if contentRange != nil { if contentRange != nil {
if contentRange.length > 0 { if contentRange.length > 0 {
setCommonHeaders(w, int(contentRange.length)) w.Header().Set("Content-Length", strconv.FormatInt(contentRange.length, 10))
setCommonHeaders(w)
} else { } else {
setCommonHeaders(w, int(metadata.Size)) w.Header().Set("Content-Length", strconv.FormatInt(metadata.Size, 10))
setCommonHeaders(w)
} }
} else { } else {
setCommonHeaders(w, int(metadata.Size)) w.Header().Set("Content-Length", strconv.FormatInt(metadata.Size, 10))
setCommonHeaders(w)
} }
// set object headers // set object headers
lastModified := metadata.Created.Format(http.TimeFormat) lastModified := metadata.Created.Format(http.TimeFormat)

@ -206,15 +206,20 @@ func generateListMultipartUploadsResponse(bucket string, metadata fs.BucketMulti
return listMultipartUploadsResponse return listMultipartUploadsResponse
} }
// writeSuccessResponse write success headers // writeSuccessResponse write success headers and response if any.
func writeSuccessResponse(w http.ResponseWriter) { func writeSuccessResponse(w http.ResponseWriter, response []byte) {
setCommonHeaders(w, 0) setCommonHeaders(w)
w.WriteHeader(http.StatusOK) if response == nil {
w.WriteHeader(http.StatusOK)
return
}
w.Write(response)
w.(http.Flusher).Flush()
} }
// writeSuccessNoContent write success headers with http status 204 // writeSuccessNoContent write success headers with http status 204
func writeSuccessNoContent(w http.ResponseWriter) { func writeSuccessNoContent(w http.ResponseWriter) {
setCommonHeaders(w, 0) setCommonHeaders(w)
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
@ -225,12 +230,13 @@ func writeErrorResponse(w http.ResponseWriter, req *http.Request, errorType int,
errorResponse := getErrorResponse(error, resource) errorResponse := getErrorResponse(error, resource)
encodedErrorResponse := encodeErrorResponse(errorResponse) encodedErrorResponse := encodeErrorResponse(errorResponse)
// set common headers // set common headers
setCommonHeaders(w, len(encodedErrorResponse)) setCommonHeaders(w)
// write Header // write Header
w.WriteHeader(error.HTTPStatusCode) w.WriteHeader(error.HTTPStatusCode)
// HEAD should have no body, do not attempt to write to it // HEAD should have no body, do not attempt to write to it
if req.Method != "HEAD" { if req.Method != "HEAD" {
// write error body // write error body
w.Write(encodedErrorResponse) w.Write(encodedErrorResponse)
w.(http.Flusher).Flush()
} }
} }

@ -14,9 +14,6 @@ environment:
# scripts that run after cloning repository # scripts that run after cloning repository
install: install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH% - set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- rd C:\Go /s /q
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.5.1.windows-amd64.zip
- 7z x go1.5.1.windows-amd64.zip -oC:\ >nul
- go version - go version
- go env - go env

@ -58,8 +58,8 @@ func (api CloudStorageAPI) GetBucketLocationHandler(w http.ResponseWriter, req *
// we bring in a mechanism of configurable regions. For the time being // we bring in a mechanism of configurable regions. For the time being
// default region is empty i.e 'us-east-1'. // default region is empty i.e 'us-east-1'.
encodedSuccessResponse := encodeSuccessResponse(LocationResponse{}) // generate response encodedSuccessResponse := encodeSuccessResponse(LocationResponse{}) // generate response
setCommonHeaders(w, len(encodedSuccessResponse)) // write headers setCommonHeaders(w) // write headers
w.Write(encodedSuccessResponse) // write body writeSuccessResponse(w, encodedSuccessResponse)
} }
// ListMultipartUploadsHandler - GET Bucket (List Multipart uploads) // ListMultipartUploadsHandler - GET Bucket (List Multipart uploads)
@ -104,10 +104,10 @@ func (api CloudStorageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, re
// generate response // generate response
response := generateListMultipartUploadsResponse(bucket, resources) response := generateListMultipartUploadsResponse(bucket, resources)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // write headers.
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
} }
// ListObjectsHandler - GET Bucket (List Objects) // ListObjectsHandler - GET Bucket (List Objects)
@ -139,13 +139,13 @@ func (api CloudStorageAPI) ListObjectsHandler(w http.ResponseWriter, req *http.R
objects, resources, err := api.Filesystem.ListObjects(bucket, resources) objects, resources, err := api.Filesystem.ListObjects(bucket, resources)
if err == nil { if err == nil {
// generate response // Generate response
response := generateListObjectsResponse(bucket, objects, resources) response := generateListObjectsResponse(bucket, objects, resources)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // Write headers
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // Write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
return return
} }
switch err.ToGoError().(type) { switch err.ToGoError().(type) {
@ -180,9 +180,9 @@ func (api CloudStorageAPI) ListBucketsHandler(w http.ResponseWriter, req *http.R
response := generateListBucketsResponse(buckets) response := generateListBucketsResponse(buckets)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // write headers
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write response // write response
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
return return
} }
errorIf(err.Trace(), "ListBuckets failed.", nil) errorIf(err.Trace(), "ListBuckets failed.", nil)
@ -265,7 +265,7 @@ func (api CloudStorageAPI) PutBucketHandler(w http.ResponseWriter, req *http.Req
} }
// Make sure to add Location information here only for bucket // Make sure to add Location information here only for bucket
w.Header().Set("Location", "/"+bucket) w.Header().Set("Location", "/"+bucket)
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
// PostPolicyBucketHandler - POST policy // PostPolicyBucketHandler - POST policy
@ -348,7 +348,7 @@ func (api CloudStorageAPI) PostPolicyBucketHandler(w http.ResponseWriter, req *h
return return
} }
w.Header().Set("ETag", "\""+metadata.Md5+"\"") w.Header().Set("ETag", "\""+metadata.Md5+"\"")
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
// PutBucketACLHandler - PUT Bucket ACL // PutBucketACLHandler - PUT Bucket ACL
@ -384,7 +384,7 @@ func (api CloudStorageAPI) PutBucketACLHandler(w http.ResponseWriter, req *http.
} }
return return
} }
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
// GetBucketACLHandler - GET ACL on a Bucket // GetBucketACLHandler - GET ACL on a Bucket
@ -417,13 +417,13 @@ func (api CloudStorageAPI) GetBucketACLHandler(w http.ResponseWriter, req *http.
} }
return return
} }
// generate response // Generate response
response := generateAccessControlPolicyResponse(bucketMetadata.ACL) response := generateAccessControlPolicyResponse(bucketMetadata.ACL)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // Write headers
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // Write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
} }
// HeadBucketHandler - HEAD Bucket // HeadBucketHandler - HEAD Bucket
@ -458,7 +458,7 @@ func (api CloudStorageAPI) HeadBucketHandler(w http.ResponseWriter, req *http.Re
} }
return return
} }
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
// DeleteBucketHandler - Delete bucket // DeleteBucketHandler - Delete bucket

@ -194,7 +194,7 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, req *http.Req
return return
} }
w.Header().Set("ETag", "\""+metadata.Md5+"\"") w.Header().Set("ETag", "\""+metadata.Md5+"\"")
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
/// Multipart CloudStorageAPI /// Multipart CloudStorageAPI
@ -237,9 +237,9 @@ func (api CloudStorageAPI) NewMultipartUploadHandler(w http.ResponseWriter, req
response := generateInitiateMultipartUploadResponse(bucket, object, uploadID) response := generateInitiateMultipartUploadResponse(bucket, object, uploadID)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // write headers
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
} }
// PutObjectPartHandler - Upload part // PutObjectPartHandler - Upload part
@ -326,7 +326,7 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, req *http
return return
} }
w.Header().Set("ETag", "\""+calculatedMD5+"\"") w.Header().Set("ETag", "\""+calculatedMD5+"\"")
writeSuccessResponse(w) writeSuccessResponse(w, nil)
} }
// AbortMultipartUploadHandler - Abort multipart upload // AbortMultipartUploadHandler - Abort multipart upload
@ -412,10 +412,10 @@ func (api CloudStorageAPI) ListObjectPartsHandler(w http.ResponseWriter, req *ht
} }
response := generateListPartsResponse(objectResourcesMetadata) response := generateListPartsResponse(objectResourcesMetadata)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // write headers.
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
} }
// CompleteMultipartUploadHandler - Complete multipart upload // CompleteMultipartUploadHandler - Complete multipart upload
@ -478,9 +478,9 @@ func (api CloudStorageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter,
response := generateCompleteMultpartUploadResponse(bucket, object, req.URL.String(), metadata.Md5) response := generateCompleteMultpartUploadResponse(bucket, object, req.URL.String(), metadata.Md5)
encodedSuccessResponse := encodeSuccessResponse(response) encodedSuccessResponse := encodeSuccessResponse(response)
// write headers // write headers
setCommonHeaders(w, len(encodedSuccessResponse)) setCommonHeaders(w)
// write body // write success response.
w.Write(encodedSuccessResponse) writeSuccessResponse(w, encodedSuccessResponse)
} }
/// Delete CloudStorageAPI /// Delete CloudStorageAPI

Loading…
Cancel
Save