Initial QSfera import
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"net/http"
|
||||
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var sabreException = map[int]string{
|
||||
|
||||
// the commented states have no corresponding exception in sabre/dav,
|
||||
// see https://github.com/sabre-io/dav/tree/master/lib/DAV/Exception
|
||||
|
||||
// http.StatusMultipleChoices: "Multiple Choices",
|
||||
// http.StatusMovedPermanently: "Moved Permanently",
|
||||
// http.StatusFound: "Found",
|
||||
// http.StatusSeeOther: "See Other",
|
||||
// http.StatusNotModified: "Not Modified",
|
||||
// http.StatusUseProxy: "Use Proxy",
|
||||
// http.StatusTemporaryRedirect: "Temporary Redirect",
|
||||
// http.StatusPermanentRedirect: "Permanent Redirect",
|
||||
|
||||
http.StatusBadRequest: "Sabre\\DAV\\Exception\\BadRequest",
|
||||
http.StatusUnauthorized: "Sabre\\DAV\\Exception\\NotAuthenticated",
|
||||
http.StatusPaymentRequired: "Sabre\\DAV\\Exception\\PaymentRequired",
|
||||
http.StatusForbidden: "Sabre\\DAV\\Exception\\Forbidden", // InvalidResourceType, InvalidSyncToken, TooManyMatches
|
||||
http.StatusNotFound: "Sabre\\DAV\\Exception\\NotFound",
|
||||
http.StatusMethodNotAllowed: "Sabre\\DAV\\Exception\\MethodNotAllowed",
|
||||
// http.StatusNotAcceptable: "Not Acceptable",
|
||||
// http.StatusProxyAuthRequired: "Proxy Authentication Required",
|
||||
// http.StatusRequestTimeout: "Request Timeout",
|
||||
http.StatusConflict: "Sabre\\DAV\\Exception\\Conflict", // LockTokenMatchesRequestUri
|
||||
// http.StatusGone: "Gone",
|
||||
http.StatusLengthRequired: "Sabre\\DAV\\Exception\\LengthRequired",
|
||||
http.StatusPreconditionFailed: "Sabre\\DAV\\Exception\\PreconditionFailed",
|
||||
// http.StatusRequestEntityTooLarge: "Request Entity Too Large",
|
||||
// http.StatusRequestURITooLong: "Request URI Too Long",
|
||||
http.StatusUnsupportedMediaType: "Sabre\\DAV\\Exception\\UnsupportedMediaType", // ReportNotSupported
|
||||
http.StatusRequestedRangeNotSatisfiable: "Sabre\\DAV\\Exception\\RequestedRangeNotSatisfiable",
|
||||
// http.StatusExpectationFailed: "Expectation Failed",
|
||||
// http.StatusTeapot: "I'm a teapot",
|
||||
// http.StatusMisdirectedRequest: "Misdirected Request",
|
||||
// http.StatusUnprocessableEntity: "Unprocessable Entity",
|
||||
http.StatusLocked: "Sabre\\DAV\\Exception\\Locked", // ConflictingLock
|
||||
// http.StatusFailedDependency: "Failed Dependency",
|
||||
// http.StatusTooEarly: "Too Early",
|
||||
// http.StatusUpgradeRequired: "Upgrade Required",
|
||||
// http.StatusPreconditionRequired: "Precondition Required",
|
||||
// http.StatusTooManyRequests: "Too Many Requests",
|
||||
// http.StatusRequestHeaderFieldsTooLarge: "Request Header Fields Too Large",
|
||||
// http.StatusUnavailableForLegalReasons: "Unavailable For Legal Reasons",
|
||||
|
||||
// http.StatusInternalServerError: "Internal Server Error",
|
||||
http.StatusNotImplemented: "Sabre\\DAV\\Exception\\NotImplemented",
|
||||
// http.StatusBadGateway: "Bad Gateway",
|
||||
http.StatusServiceUnavailable: "Sabre\\DAV\\Exception\\ServiceUnavailable",
|
||||
// http.StatusGatewayTimeout: "Gateway Timeout",
|
||||
// http.StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
|
||||
// http.StatusVariantAlsoNegotiates: "Variant Also Negotiates",
|
||||
http.StatusInsufficientStorage: "Sabre\\DAV\\Exception\\InsufficientStorage",
|
||||
// http.StatusLoopDetected: "Loop Detected",
|
||||
// http.StatusNotExtended: "Not Extended",
|
||||
// http.StatusNetworkAuthenticationRequired: "Network Authentication Required",
|
||||
}
|
||||
|
||||
// SabreException returns a sabre exception text for the HTTP status code. It returns the empty
|
||||
// string if the code is unknown.
|
||||
func SabreException(code int) string {
|
||||
return sabreException[code]
|
||||
}
|
||||
|
||||
// Exception represents a ocdav exception
|
||||
type Exception struct {
|
||||
Code int
|
||||
Message string
|
||||
Header string
|
||||
}
|
||||
|
||||
// Marshal just calls the xml marshaller for a given exception.
|
||||
func Marshal(code int, message string, header string) ([]byte, error) {
|
||||
xmlstring, err := xml.Marshal(&ErrorXML{
|
||||
Xmlnsd: "DAV",
|
||||
Xmlnss: "http://sabredav.org/ns",
|
||||
Exception: sabreException[code],
|
||||
Message: message,
|
||||
Header: header,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(xml.Header)
|
||||
buf.Write(xmlstring)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// ErrorXML holds the xml representation of an error
|
||||
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error
|
||||
type ErrorXML struct {
|
||||
XMLName xml.Name `xml:"d:error"`
|
||||
Xmlnsd string `xml:"xmlns:d,attr"`
|
||||
Xmlnss string `xml:"xmlns:s,attr"`
|
||||
Exception string `xml:"s:exception"`
|
||||
Message string `xml:"s:message"`
|
||||
InnerXML []byte `xml:",innerxml"`
|
||||
// Header is used to indicate the conflicting request header
|
||||
Header string `xml:"s:header,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrInvalidDepth is an invalid depth header error
|
||||
ErrInvalidDepth = errors.New("webdav: invalid depth")
|
||||
// ErrInvalidPropfind is an invalid propfind error
|
||||
ErrInvalidPropfind = errors.New("webdav: invalid propfind")
|
||||
// ErrInvalidProppatch is an invalid proppatch error
|
||||
ErrInvalidProppatch = errors.New("webdav: invalid proppatch")
|
||||
// ErrInvalidLockInfo is an invalid lock error
|
||||
ErrInvalidLockInfo = errors.New("webdav: invalid lock info")
|
||||
// ErrUnsupportedLockInfo is an unsupported lock error
|
||||
ErrUnsupportedLockInfo = errors.New("webdav: unsupported lock info")
|
||||
// ErrInvalidTimeout is an invalid timeout error
|
||||
ErrInvalidTimeout = errors.New("webdav: invalid timeout")
|
||||
// ErrInvalidIfHeader is an invalid if header error
|
||||
ErrInvalidIfHeader = errors.New("webdav: invalid If header")
|
||||
// ErrUnsupportedMethod is an unsupported method error
|
||||
ErrUnsupportedMethod = errors.New("webdav: unsupported method")
|
||||
// ErrInvalidLockToken is an invalid lock token error
|
||||
ErrInvalidLockToken = errors.New("webdav: invalid lock token")
|
||||
// ErrConfirmationFailed is returned by a LockSystem's Confirm method.
|
||||
ErrConfirmationFailed = errors.New("webdav: confirmation failed")
|
||||
// ErrForbidden is returned by a LockSystem's Unlock method.
|
||||
ErrForbidden = errors.New("webdav: forbidden")
|
||||
// ErrLocked is returned by a LockSystem's Create, Refresh and Unlock methods.
|
||||
ErrLocked = errors.New("webdav: locked")
|
||||
// ErrNoSuchLock is returned by a LockSystem's Refresh and Unlock methods.
|
||||
ErrNoSuchLock = errors.New("webdav: no such lock")
|
||||
// ErrNotImplemented is returned when hitting not implemented code paths
|
||||
ErrNotImplemented = errors.New("webdav: not implemented")
|
||||
)
|
||||
|
||||
// HandleErrorStatus checks the status code, logs a Debug or Error level message
|
||||
// and writes an appropriate http status
|
||||
func HandleErrorStatus(log *zerolog.Logger, w http.ResponseWriter, s *rpc.Status) {
|
||||
hsc := status.HTTPStatusFromCode(s.Code)
|
||||
if hsc == http.StatusInternalServerError {
|
||||
log.Error().Interface("status", s).Int("code", hsc).Msg(http.StatusText(hsc))
|
||||
} else {
|
||||
log.Debug().Interface("status", s).Int("code", hsc).Msg(http.StatusText(hsc))
|
||||
}
|
||||
w.WriteHeader(hsc)
|
||||
}
|
||||
|
||||
// HandleWebdavError checks the status code, logs an error and creates a webdav response body
|
||||
// if needed
|
||||
func HandleWebdavError(log *zerolog.Logger, w http.ResponseWriter, b []byte, err error) {
|
||||
if err != nil {
|
||||
log.Error().Msgf("error marshaling xml response: %s", b)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_, err = w.Write(b)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("error writing response")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user