2
2
mirror of https://github.com/octoleo/restic.git synced 2024-06-07 11:30:49 +00:00
restic/Godeps/_workspace/src/github.com/minio/minio-go/api-error-response.go

250 lines
7.7 KiB
Go
Raw Normal View History

2015-12-28 20:23:53 +00:00
/*
* Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015 Minio, Inc.
*
* 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.
*/
package minio
import (
"encoding/xml"
"fmt"
"net/http"
"strconv"
)
/* **** SAMPLE ERROR RESPONSE ****
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<BucketName>bucketName</BucketName>
<Key>objectName</Key>
<RequestId>F19772218238A85A</RequestId>
<HostId>GuWkjyviSiGHizehqpmsD1ndz5NClSP19DOT+s2mv7gXGQ8/X1lhbDGiIJEXpGFD</HostId>
</Error>
*/
2016-01-07 19:23:38 +00:00
// ErrorResponse - Is the typed error returned by all API operations.
2015-12-28 20:23:53 +00:00
type ErrorResponse struct {
XMLName xml.Name `xml:"Error" json:"-"`
Code string
Message string
BucketName string
Key string
RequestID string `xml:"RequestId"`
HostID string `xml:"HostId"`
2016-01-07 19:23:38 +00:00
// Region where the bucket is located. This header is returned
// only in HEAD bucket and ListObjects response.
2015-12-28 20:23:53 +00:00
AmzBucketRegion string
}
2016-01-07 19:23:38 +00:00
// ToErrorResponse - Returns parsed ErrorResponse struct from body and
// http headers.
2015-12-28 20:23:53 +00:00
//
// For example:
//
// import s3 "github.com/minio/minio-go"
// ...
// ...
// reader, stat, err := s3.GetObject(...)
// if err != nil {
// resp := s3.ToErrorResponse(err)
// }
// ...
func ToErrorResponse(err error) ErrorResponse {
switch err := err.(type) {
case ErrorResponse:
return err
default:
return ErrorResponse{}
}
}
2016-01-07 19:23:38 +00:00
// Error - Returns HTTP error string
2015-12-28 20:23:53 +00:00
func (e ErrorResponse) Error() string {
return e.Message
}
2016-01-07 19:23:38 +00:00
// Common string for errors to report issue location in unexpected
// cases.
2015-12-28 20:23:53 +00:00
const (
reportIssue = "Please report this issue at https://github.com/minio/minio-go/issues."
)
2016-01-07 19:23:38 +00:00
// HTTPRespToErrorResponse returns a new encoded ErrorResponse
// structure as error.
2015-12-28 20:23:53 +00:00
func HTTPRespToErrorResponse(resp *http.Response, bucketName, objectName string) error {
if resp == nil {
msg := "Response is empty. " + reportIssue
return ErrInvalidArgument(msg)
}
2016-01-07 19:23:38 +00:00
var errResp ErrorResponse
err := xmlDecoder(resp.Body, &errResp)
// Xml decoding failed with no body, fall back to HTTP headers.
2015-12-28 20:23:53 +00:00
if err != nil {
switch resp.StatusCode {
case http.StatusNotFound:
if objectName == "" {
2016-01-07 19:23:38 +00:00
errResp = ErrorResponse{
2015-12-28 20:23:53 +00:00
Code: "NoSuchBucket",
Message: "The specified bucket does not exist.",
BucketName: bucketName,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
AmzBucketRegion: resp.Header.Get("x-amz-bucket-region"),
}
} else {
2016-01-07 19:23:38 +00:00
errResp = ErrorResponse{
2015-12-28 20:23:53 +00:00
Code: "NoSuchKey",
Message: "The specified key does not exist.",
BucketName: bucketName,
Key: objectName,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
AmzBucketRegion: resp.Header.Get("x-amz-bucket-region"),
}
}
case http.StatusForbidden:
2016-01-07 19:23:38 +00:00
errResp = ErrorResponse{
2015-12-28 20:23:53 +00:00
Code: "AccessDenied",
Message: "Access Denied.",
BucketName: bucketName,
Key: objectName,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
AmzBucketRegion: resp.Header.Get("x-amz-bucket-region"),
}
case http.StatusConflict:
2016-01-07 19:23:38 +00:00
errResp = ErrorResponse{
2015-12-28 20:23:53 +00:00
Code: "Conflict",
Message: "Bucket not empty.",
BucketName: bucketName,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
AmzBucketRegion: resp.Header.Get("x-amz-bucket-region"),
}
default:
2016-01-07 19:23:38 +00:00
errResp = ErrorResponse{
2015-12-28 20:23:53 +00:00
Code: resp.Status,
Message: resp.Status,
BucketName: bucketName,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
AmzBucketRegion: resp.Header.Get("x-amz-bucket-region"),
}
}
}
2016-01-07 19:23:38 +00:00
// AccessDenied without a signature mismatch code, usually means
// that the bucket policy has certain restrictions where some API
// operations are not allowed. Handle this case so that top level
// callers can interpret this easily and fall back if needed to a
// lower functionality call. Read each individual API specific
// code for such fallbacks.
if errResp.Code == "AccessDenied" && errResp.Message == "Access Denied" {
errResp.Code = "NotImplemented"
errResp.Message = "Operation is not allowed according to your bucket policy."
}
return errResp
2015-12-28 20:23:53 +00:00
}
2016-01-07 19:23:38 +00:00
// ErrEntityTooLarge - Input size is larger than supported maximum.
2015-12-28 20:23:53 +00:00
func ErrEntityTooLarge(totalSize int64, bucketName, objectName string) error {
msg := fmt.Sprintf("Your proposed upload size %d exceeds the maximum allowed object size '5GiB' for single PUT operation.", totalSize)
return ErrorResponse{
Code: "EntityTooLarge",
Message: msg,
BucketName: bucketName,
Key: objectName,
}
}
2016-01-07 19:23:38 +00:00
// ErrEntityTooSmall - Input size is smaller than supported minimum.
func ErrEntityTooSmall(totalSize int64, bucketName, objectName string) error {
msg := fmt.Sprintf("Your proposed upload size %d is below the minimum allowed object size '0B' for single PUT operation.", totalSize)
return ErrorResponse{
Code: "EntityTooLarge",
Message: msg,
BucketName: bucketName,
Key: objectName,
}
}
// ErrUnexpectedShortRead - Unexpected shorter read of input buffer from
// target.
2015-12-28 20:23:53 +00:00
func ErrUnexpectedShortRead(totalRead, totalSize int64, bucketName, objectName string) error {
msg := fmt.Sprintf("Data read %s is shorter than the size %s of input buffer.",
strconv.FormatInt(totalRead, 10), strconv.FormatInt(totalSize, 10))
return ErrorResponse{
Code: "UnexpectedShortRead",
Message: msg,
BucketName: bucketName,
Key: objectName,
}
}
2016-01-07 19:23:38 +00:00
// ErrUnexpectedEOF - Unexpected end of file reached.
2015-12-28 20:23:53 +00:00
func ErrUnexpectedEOF(totalRead, totalSize int64, bucketName, objectName string) error {
msg := fmt.Sprintf("Data read %s is not equal to the size %s of the input Reader.",
strconv.FormatInt(totalRead, 10), strconv.FormatInt(totalSize, 10))
return ErrorResponse{
Code: "UnexpectedEOF",
Message: msg,
BucketName: bucketName,
Key: objectName,
}
}
2016-01-07 19:23:38 +00:00
// ErrInvalidBucketName - Invalid bucket name response.
2015-12-28 20:23:53 +00:00
func ErrInvalidBucketName(message string) error {
return ErrorResponse{
Code: "InvalidBucketName",
Message: message,
RequestID: "minio",
}
}
2016-01-07 19:23:38 +00:00
// ErrInvalidObjectName - Invalid object name response.
2015-12-28 20:23:53 +00:00
func ErrInvalidObjectName(message string) error {
return ErrorResponse{
Code: "NoSuchKey",
Message: message,
RequestID: "minio",
}
}
2016-01-07 19:23:38 +00:00
// ErrInvalidParts - Invalid number of parts.
2016-01-02 13:37:08 +00:00
func ErrInvalidParts(expectedParts, uploadedParts int) error {
msg := fmt.Sprintf("Unexpected number of parts found Want %d, Got %d", expectedParts, uploadedParts)
return ErrorResponse{
Code: "InvalidParts",
Message: msg,
RequestID: "minio",
}
}
2016-01-07 19:23:38 +00:00
// ErrInvalidObjectPrefix - Invalid object prefix response is
2015-12-28 20:23:53 +00:00
// similar to object name response.
var ErrInvalidObjectPrefix = ErrInvalidObjectName
2016-01-07 19:23:38 +00:00
// ErrInvalidArgument - Invalid argument response.
2015-12-28 20:23:53 +00:00
func ErrInvalidArgument(message string) error {
return ErrorResponse{
Code: "InvalidArgument",
Message: message,
RequestID: "minio",
}
}