2021-06-11 04:50:21 +00:00
|
|
|
package s3err
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
2021-06-11 04:55:13 +00:00
|
|
|
"github.com/gorilla/mux"
|
2022-07-29 07:17:28 +00:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/glog"
|
2021-06-11 04:50:21 +00:00
|
|
|
"net/http"
|
|
|
|
"strconv"
|
2021-06-11 04:55:13 +00:00
|
|
|
"strings"
|
2021-06-11 04:50:21 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type mimeType string
|
|
|
|
|
|
|
|
const (
|
|
|
|
mimeNone mimeType = ""
|
|
|
|
MimeXML mimeType = "application/xml"
|
|
|
|
)
|
|
|
|
|
2021-11-01 01:02:08 +00:00
|
|
|
func WriteXMLResponse(w http.ResponseWriter, r *http.Request, statusCode int, response interface{}) {
|
|
|
|
WriteResponse(w, r, statusCode, EncodeXMLResponse(response), MimeXML)
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 01:02:08 +00:00
|
|
|
func WriteEmptyResponse(w http.ResponseWriter, r *http.Request, statusCode int) {
|
|
|
|
WriteResponse(w, r, statusCode, []byte{}, mimeNone)
|
2021-12-07 13:20:52 +00:00
|
|
|
PostLog(r, statusCode, ErrNone)
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 01:05:34 +00:00
|
|
|
func WriteErrorResponse(w http.ResponseWriter, r *http.Request, errorCode ErrorCode) {
|
2021-06-11 04:55:13 +00:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
bucket := vars["bucket"]
|
|
|
|
object := vars["object"]
|
2021-06-11 05:17:53 +00:00
|
|
|
if strings.HasPrefix(object, "/") {
|
|
|
|
object = object[1:]
|
2021-06-11 04:55:13 +00:00
|
|
|
}
|
|
|
|
|
2021-06-11 04:50:21 +00:00
|
|
|
apiError := GetAPIError(errorCode)
|
2021-06-11 04:55:13 +00:00
|
|
|
errorResponse := getRESTErrorResponse(apiError, r.URL.Path, bucket, object)
|
2021-06-11 04:50:21 +00:00
|
|
|
encodedErrorResponse := EncodeXMLResponse(errorResponse)
|
2021-11-01 01:02:08 +00:00
|
|
|
WriteResponse(w, r, apiError.HTTPStatusCode, encodedErrorResponse, MimeXML)
|
2021-12-07 13:20:52 +00:00
|
|
|
PostLog(r, apiError.HTTPStatusCode, errorCode)
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|
|
|
|
|
2021-06-11 04:55:13 +00:00
|
|
|
func getRESTErrorResponse(err APIError, resource string, bucket, object string) RESTErrorResponse {
|
2021-06-11 04:50:21 +00:00
|
|
|
return RESTErrorResponse{
|
2021-06-11 04:55:13 +00:00
|
|
|
Code: err.Code,
|
|
|
|
BucketName: bucket,
|
2021-06-11 05:17:53 +00:00
|
|
|
Key: object,
|
2021-06-11 04:55:13 +00:00
|
|
|
Message: err.Description,
|
|
|
|
Resource: resource,
|
|
|
|
RequestID: fmt.Sprintf("%d", time.Now().UnixNano()),
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encodes the response headers into XML format.
|
|
|
|
func EncodeXMLResponse(response interface{}) []byte {
|
|
|
|
var bytesBuffer bytes.Buffer
|
|
|
|
bytesBuffer.WriteString(xml.Header)
|
|
|
|
e := xml.NewEncoder(&bytesBuffer)
|
|
|
|
e.Encode(response)
|
|
|
|
return bytesBuffer.Bytes()
|
|
|
|
}
|
|
|
|
|
2021-11-01 01:02:08 +00:00
|
|
|
func setCommonHeaders(w http.ResponseWriter, r *http.Request) {
|
2021-06-11 04:50:21 +00:00
|
|
|
w.Header().Set("x-amz-request-id", fmt.Sprintf("%d", time.Now().UnixNano()))
|
|
|
|
w.Header().Set("Accept-Ranges", "bytes")
|
2021-11-01 01:06:43 +00:00
|
|
|
if r.Header.Get("Origin") != "" {
|
|
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
|
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
|
|
}
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 01:02:08 +00:00
|
|
|
func WriteResponse(w http.ResponseWriter, r *http.Request, statusCode int, response []byte, mType mimeType) {
|
|
|
|
setCommonHeaders(w, r)
|
2021-06-11 04:50:21 +00:00
|
|
|
if response != nil {
|
|
|
|
w.Header().Set("Content-Length", strconv.Itoa(len(response)))
|
|
|
|
}
|
|
|
|
if mType != mimeNone {
|
|
|
|
w.Header().Set("Content-Type", string(mType))
|
|
|
|
}
|
|
|
|
w.WriteHeader(statusCode)
|
|
|
|
if response != nil {
|
|
|
|
glog.V(4).Infof("status %d %s: %s", statusCode, mType, string(response))
|
|
|
|
_, err := w.Write(response)
|
|
|
|
if err != nil {
|
|
|
|
glog.V(0).Infof("write err: %v", err)
|
|
|
|
}
|
|
|
|
w.(http.Flusher).Flush()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If none of the http routes match respond with MethodNotAllowed
|
|
|
|
func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
glog.V(0).Infof("unsupported %s %s", r.Method, r.RequestURI)
|
2021-11-01 01:05:34 +00:00
|
|
|
WriteErrorResponse(w, r, ErrMethodNotAllowed)
|
2021-06-11 04:50:21 +00:00
|
|
|
}
|