| 
									
										
										
										
											2015-02-15 16:48:15 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-07-25 08:51:40 +08:00
										 |  |  |  * Minio Cloud Storage, (C) 2015 Minio, Inc. | 
					
						
							| 
									
										
										
										
											2015-02-15 16:48:15 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-19 15:52:01 +08:00
										 |  |  | package main | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2015-07-15 05:29:56 +08:00
										 |  |  | 	"crypto/rand" | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	"encoding/xml" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2015-09-19 15:52:01 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/fs" | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | //// helpers
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-15 05:29:56 +08:00
										 |  |  | // Static alphaNumeric table used for generating unique request ids
 | 
					
						
							|  |  |  | var alphaNumericTable = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // generateRequestID generate request id
 | 
					
						
							|  |  |  | func generateRequestID() []byte { | 
					
						
							|  |  |  | 	alpha := make([]byte, 16) | 
					
						
							|  |  |  | 	rand.Read(alpha) | 
					
						
							|  |  |  | 	for i := 0; i < 16; i++ { | 
					
						
							|  |  |  | 		alpha[i] = alphaNumericTable[alpha[i]%byte(len(alphaNumericTable))] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return alpha | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | // Write http common headers
 | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | func setCommonHeaders(w http.ResponseWriter, contentLength int) { | 
					
						
							| 
									
										
										
										
											2015-07-15 05:29:56 +08:00
										 |  |  | 	// set unique request ID for each reply
 | 
					
						
							|  |  |  | 	w.Header().Set("X-Amz-Request-Id", string(generateRequestID())) | 
					
						
							| 
									
										
										
										
											2015-10-17 11:02:37 +08:00
										 |  |  | 	w.Header().Set("Server", ("Minio/" + minioReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")")) | 
					
						
							| 
									
										
										
										
											2015-03-11 16:01:49 +08:00
										 |  |  | 	w.Header().Set("Accept-Ranges", "bytes") | 
					
						
							| 
									
										
										
										
											2015-03-29 09:00:55 +08:00
										 |  |  | 	w.Header().Set("Connection", "close") | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	// should be set to '0' by default
 | 
					
						
							| 
									
										
										
										
											2015-05-16 11:44:42 +08:00
										 |  |  | 	w.Header().Set("Content-Length", strconv.Itoa(contentLength)) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | // Write error response headers
 | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | func encodeErrorResponse(response interface{}) []byte { | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	var bytesBuffer bytes.Buffer | 
					
						
							|  |  |  | 	// write common headers
 | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | 	e := xml.NewEncoder(&bytesBuffer) | 
					
						
							| 
									
										
										
										
											2015-09-10 06:11:37 +08:00
										 |  |  | 	e.Encode(response) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	return bytesBuffer.Bytes() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | // Write object header
 | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | func setObjectHeaders(w http.ResponseWriter, metadata fs.ObjectMetadata, contentRange *httpRange) { | 
					
						
							| 
									
										
										
										
											2015-07-29 10:33:56 +08:00
										 |  |  | 	// set common headers
 | 
					
						
							|  |  |  | 	if contentRange != nil { | 
					
						
							|  |  |  | 		if contentRange.length > 0 { | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | 			setCommonHeaders(w, int(contentRange.length)) | 
					
						
							| 
									
										
										
										
											2015-07-29 10:33:56 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | 			setCommonHeaders(w, int(metadata.Size)) | 
					
						
							| 
									
										
										
										
											2015-07-29 10:33:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | 		setCommonHeaders(w, int(metadata.Size)) | 
					
						
							| 
									
										
										
										
											2015-07-29 10:33:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// set object headers
 | 
					
						
							| 
									
										
										
										
											2015-05-26 11:10:01 +08:00
										 |  |  | 	lastModified := metadata.Created.Format(http.TimeFormat) | 
					
						
							| 
									
										
										
										
											2015-05-16 11:44:42 +08:00
										 |  |  | 	// object related headers
 | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | 	w.Header().Set("Content-Type", "application/octet-stream") | 
					
						
							|  |  |  | 	w.Header().Set("ETag", "\""+metadata.Md5+"\"") | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	w.Header().Set("Last-Modified", lastModified) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-30 12:06:47 +08:00
										 |  |  | 	// set content range
 | 
					
						
							| 
									
										
										
										
											2015-07-29 10:33:56 +08:00
										 |  |  | 	if contentRange != nil { | 
					
						
							|  |  |  | 		if contentRange.start > 0 || contentRange.length > 0 { | 
					
						
							|  |  |  | 			w.Header().Set("Content-Range", contentRange.String()) | 
					
						
							|  |  |  | 			w.WriteHeader(http.StatusPartialContent) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-11 16:01:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | func encodeSuccessResponse(response interface{}) []byte { | 
					
						
							| 
									
										
										
										
											2015-03-29 09:00:55 +08:00
										 |  |  | 	var bytesBuffer bytes.Buffer | 
					
						
							| 
									
										
										
										
											2015-10-04 15:27:49 +08:00
										 |  |  | 	e := xml.NewEncoder(&bytesBuffer) | 
					
						
							| 
									
										
										
										
											2015-09-10 06:11:37 +08:00
										 |  |  | 	e.Encode(response) | 
					
						
							| 
									
										
										
										
											2015-02-11 19:23:15 +08:00
										 |  |  | 	return bytesBuffer.Bytes() | 
					
						
							|  |  |  | } |