Use standard error messages

This commit is contained in:
Lena Fuhrimann 2017-04-09 16:28:57 +02:00
parent 9c697a99f5
commit 39521e331d
15 changed files with 87 additions and 105 deletions

View file

@ -32,8 +32,7 @@ func BucketViewHandler(s3 S3Client) http.Handler {
t, err := template.ParseFiles(l, p)
if err != nil {
msg := "error parsing templates"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
@ -42,14 +41,12 @@ func BucketViewHandler(s3 S3Client) http.Handler {
objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh)
for object := range objectCh {
if object.Err != nil {
msg := "error listing objects"
code := http.StatusInternalServerError
if object.Err.Error() == "The specified bucket does not exist." {
msg = "bucket not found"
if object.Err.Error() == ErrBucketDoesNotExist {
code = http.StatusNotFound
}
handleHTTPError(w, msg, object.Err, code)
handleHTTPError(w, code, object.Err)
return
}
objectWithIcon := ObjectWithIcon{object, icon(object.Key)}
@ -63,8 +60,7 @@ func BucketViewHandler(s3 S3Client) http.Handler {
err = t.ExecuteTemplate(w, "layout", bucketPage)
if err != nil {
msg := "error executing template"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
})

View file

@ -88,7 +88,7 @@ func TestBucketViewHandler(t *testing.T) {
s3: &S3ClientMock{},
bucketName: "testBucket",
expectedStatusCode: http.StatusNotFound,
expectedBodyCountains: "bucket not found\n",
expectedBodyCountains: http.StatusText(http.StatusNotFound),
},
"s3 error": {
s3: &S3ClientMock{
@ -96,7 +96,7 @@ func TestBucketViewHandler(t *testing.T) {
},
bucketName: "testBucket",
expectedStatusCode: http.StatusInternalServerError,
expectedBodyCountains: "error listing objects\n",
expectedBodyCountains: http.StatusText(http.StatusInternalServerError),
},
}

View file

@ -14,22 +14,19 @@ func BucketsViewHandler(s3 S3Client) http.Handler {
t, err := template.ParseFiles(l, p)
if err != nil {
msg := "error parsing templates"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
buckets, err := s3.ListBuckets()
if err != nil {
msg := "error listing buckets"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
err = t.ExecuteTemplate(w, "layout", buckets)
if err != nil {
msg := "error executing template"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
})

View file

@ -37,7 +37,7 @@ func TestBucketsViewHandler(t *testing.T) {
Err: errors.New("mocked S3 error"),
},
expectedStatusCode: http.StatusInternalServerError,
expectedBodyContains: "error listing buckets\n",
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
},
}

View file

@ -14,15 +14,13 @@ func CreateBucketHandler(s3 S3Client) http.Handler {
err := json.NewDecoder(r.Body).Decode(&bucket)
if err != nil {
msg := "error decoding json"
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
handleHTTPError(w, http.StatusUnprocessableEntity, err)
return
}
err = s3.MakeBucket(bucket.Name, "")
if err != nil {
msg := "error making bucket"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
@ -31,8 +29,7 @@ func CreateBucketHandler(s3 S3Client) http.Handler {
err = json.NewEncoder(w).Encode(bucket)
if err != nil {
msg := "error encoding json"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
})

View file

@ -14,36 +14,36 @@ func TestCreateBucketHandler(t *testing.T) {
assert := assert.New(t)
tests := map[string]struct {
s3 S3Client
body string
expectedStatusCode int
expectedBody string
s3 S3Client
body string
expectedStatusCode int
expectedBodyContains string
}{
"success": {
s3: &S3ClientMock{},
body: "{\"name\":\"myBucket\"}",
expectedStatusCode: http.StatusCreated,
expectedBody: "{\"name\":\"myBucket\",\"creationDate\":\"0001-01-01T00:00:00Z\"}\n",
s3: &S3ClientMock{},
body: "{\"name\":\"myBucket\"}",
expectedStatusCode: http.StatusCreated,
expectedBodyContains: "{\"name\":\"myBucket\",\"creationDate\":\"0001-01-01T00:00:00Z\"}\n",
},
"empty request": {
s3: &S3ClientMock{},
body: "",
expectedStatusCode: http.StatusUnprocessableEntity,
expectedBody: "error decoding json\n",
s3: &S3ClientMock{},
body: "",
expectedStatusCode: http.StatusUnprocessableEntity,
expectedBodyContains: http.StatusText(http.StatusUnprocessableEntity),
},
"malformed request": {
s3: &S3ClientMock{},
body: "}",
expectedStatusCode: http.StatusUnprocessableEntity,
expectedBody: "error decoding json\n",
s3: &S3ClientMock{},
body: "}",
expectedStatusCode: http.StatusUnprocessableEntity,
expectedBodyContains: http.StatusText(http.StatusUnprocessableEntity),
},
"s3 error": {
s3: &S3ClientMock{
Err: errors.New("mocked S3 error"),
},
body: "{\"name\":\"myBucket\"}",
expectedStatusCode: http.StatusInternalServerError,
expectedBody: "error making bucket\n",
body: "{\"name\":\"myBucket\"}",
expectedStatusCode: http.StatusInternalServerError,
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
},
}
@ -57,6 +57,6 @@ func TestCreateBucketHandler(t *testing.T) {
handler.ServeHTTP(rr, req)
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
assert.Equal(tc.expectedBody, rr.Body.String(), tcID)
assert.Contains(rr.Body.String(), tc.expectedBodyContains, tcID)
}
}

View file

@ -28,8 +28,7 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
err := json.NewDecoder(r.Body).Decode(&copy)
if err != nil {
msg := "error decoding json"
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
@ -37,8 +36,7 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
objectSource := fmt.Sprintf("/%s/%s", copy.SourceBucketName, copy.SourceObjectName)
err = s3.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds)
if err != nil {
msg := "error copying object"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
@ -47,30 +45,26 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
err = json.NewEncoder(w).Encode(copy)
if err != nil {
msg := "error encoding json"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
} else {
err := r.ParseMultipartForm(32 << 20)
if err != nil {
msg := "error parsing form"
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
handleHTTPError(w, http.StatusUnprocessableEntity, err)
return
}
file, handler, err := r.FormFile("file")
if err != nil {
msg := "error getting form file"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
defer file.Close()
_, err = s3.PutObject(vars["bucketName"], handler.Filename, file, contentTypeOctetStream)
if err != nil {
msg := "error putting object"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}

View file

@ -13,8 +13,7 @@ func DeleteBucketHandler(s3 S3Client) http.Handler {
err := s3.RemoveBucket(vars["bucketName"])
if err != nil {
msg := "error removing bucket"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}

View file

@ -13,21 +13,21 @@ func TestDeleteBucketHandler(t *testing.T) {
assert := assert.New(t)
tests := map[string]struct {
s3 S3Client
expectedStatusCode int
expectedBody string
s3 S3Client
expectedStatusCode int
expectedBodyContains string
}{
"success": {
s3: &S3ClientMock{},
expectedStatusCode: http.StatusNoContent,
expectedBody: "",
s3: &S3ClientMock{},
expectedStatusCode: http.StatusNoContent,
expectedBodyContains: "",
},
"s3 error": {
s3: &S3ClientMock{
Err: errors.New("mocked S3 error"),
},
expectedStatusCode: http.StatusInternalServerError,
expectedBody: "error removing bucket\n",
expectedStatusCode: http.StatusInternalServerError,
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
},
}
@ -41,6 +41,6 @@ func TestDeleteBucketHandler(t *testing.T) {
handler.ServeHTTP(rr, req)
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
assert.Equal(tc.expectedBody, rr.Body.String(), tcID)
assert.Contains(rr.Body.String(), tc.expectedBodyContains, tcID)
}
}

View file

@ -13,8 +13,7 @@ func DeleteObjectHandler(s3 S3Client) http.Handler {
err := s3.RemoveObject(vars["bucketName"], vars["objectName"])
if err != nil {
msg := "error removing object"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}

View file

@ -13,21 +13,21 @@ func TestDeleteObjectHandler(t *testing.T) {
assert := assert.New(t)
tests := map[string]struct {
s3 S3Client
expectedStatusCode int
expectedBody string
s3 S3Client
expectedStatusCode int
expectedBodyContains string
}{
"success": {
s3: &S3ClientMock{},
expectedStatusCode: http.StatusNoContent,
expectedBody: "",
s3: &S3ClientMock{},
expectedStatusCode: http.StatusNoContent,
expectedBodyContains: "",
},
"s3 error": {
s3: &S3ClientMock{
Err: errors.New("mocked S3 error"),
},
expectedStatusCode: http.StatusInternalServerError,
expectedBody: "error removing object\n",
expectedStatusCode: http.StatusInternalServerError,
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
},
}
@ -41,6 +41,6 @@ func TestDeleteObjectHandler(t *testing.T) {
handler.ServeHTTP(rr, req)
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
assert.Equal(tc.expectedBody, rr.Body.String(), tcID)
assert.Contains(rr.Body.String(), tc.expectedBodyContains, tcID)
}
}

24
errors.go Normal file
View file

@ -0,0 +1,24 @@
package main
import (
"log"
"net/http"
)
// Common error messages within the app
const (
ErrBucketDoesNotExist = "The specified bucket does not exist."
ErrKeyDoesNotExist = "The specified key does not exist."
)
// handleHTTPError handles HTTP errors
func handleHTTPError(w http.ResponseWriter, statusCode int, err error) {
msg := http.StatusText(statusCode)
http.Error(w, msg, statusCode)
logMsg := msg
if err != nil {
logMsg = logMsg + ": " + err.Error()
}
log.Println(logMsg)
}

View file

@ -16,8 +16,7 @@ func GetObjectHandler(s3 S3Client) http.Handler {
object, err := s3.GetObject(vars["bucketName"], objectName)
if err != nil {
msg := "error getting object"
handleHTTPError(w, msg, err, http.StatusInternalServerError)
handleHTTPError(w, http.StatusInternalServerError, err)
return
}
@ -26,18 +25,11 @@ func GetObjectHandler(s3 S3Client) http.Handler {
_, err = io.Copy(w, object)
if err != nil {
msg := "error copying object"
code := http.StatusInternalServerError
if err.Error() == "The specified key does not exist." {
msg = "object not found"
if err.Error() == ErrBucketDoesNotExist || err.Error() == ErrKeyDoesNotExist {
code = http.StatusNotFound
}
if err.Error() == "The specified bucket does not exist." {
msg = "bucket not found"
code = http.StatusNotFound
}
handleHTTPError(w, msg, err, code)
handleHTTPError(w, code, err)
return
}
})

View file

@ -29,7 +29,7 @@ func TestGetObjectHandler(t *testing.T) {
bucketName: "testBucket",
objectName: "testObject",
expectedStatusCode: http.StatusInternalServerError,
expectedBodyCountains: "error getting object\n",
expectedBodyCountains: http.StatusText(http.StatusInternalServerError),
},
}

View file

@ -1,16 +0,0 @@
package main
import (
"log"
"net/http"
)
// handleHTTPError handles HTTP errors
func handleHTTPError(w http.ResponseWriter, msg string, err error, statusCode int) {
http.Error(w, msg, statusCode)
if err != nil {
log.Println(msg+":", err.Error())
} else {
log.Println(msg)
}
}