Use standard error messages
This commit is contained in:
parent
9c697a99f5
commit
39521e331d
15 changed files with 87 additions and 105 deletions
|
@ -32,8 +32,7 @@ func BucketViewHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
t, err := template.ParseFiles(l, p)
|
t, err := template.ParseFiles(l, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error parsing templates"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,14 +41,12 @@ func BucketViewHandler(s3 S3Client) http.Handler {
|
||||||
objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh)
|
objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh)
|
||||||
for object := range objectCh {
|
for object := range objectCh {
|
||||||
if object.Err != nil {
|
if object.Err != nil {
|
||||||
msg := "error listing objects"
|
|
||||||
code := http.StatusInternalServerError
|
code := http.StatusInternalServerError
|
||||||
if object.Err.Error() == "The specified bucket does not exist." {
|
if object.Err.Error() == ErrBucketDoesNotExist {
|
||||||
msg = "bucket not found"
|
|
||||||
code = http.StatusNotFound
|
code = http.StatusNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHTTPError(w, msg, object.Err, code)
|
handleHTTPError(w, code, object.Err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
objectWithIcon := ObjectWithIcon{object, icon(object.Key)}
|
objectWithIcon := ObjectWithIcon{object, icon(object.Key)}
|
||||||
|
@ -63,8 +60,7 @@ func BucketViewHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err = t.ExecuteTemplate(w, "layout", bucketPage)
|
err = t.ExecuteTemplate(w, "layout", bucketPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error executing template"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -88,7 +88,7 @@ func TestBucketViewHandler(t *testing.T) {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
bucketName: "testBucket",
|
bucketName: "testBucket",
|
||||||
expectedStatusCode: http.StatusNotFound,
|
expectedStatusCode: http.StatusNotFound,
|
||||||
expectedBodyCountains: "bucket not found\n",
|
expectedBodyCountains: http.StatusText(http.StatusNotFound),
|
||||||
},
|
},
|
||||||
"s3 error": {
|
"s3 error": {
|
||||||
s3: &S3ClientMock{
|
s3: &S3ClientMock{
|
||||||
|
@ -96,7 +96,7 @@ func TestBucketViewHandler(t *testing.T) {
|
||||||
},
|
},
|
||||||
bucketName: "testBucket",
|
bucketName: "testBucket",
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBodyCountains: "error listing objects\n",
|
expectedBodyCountains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,22 +14,19 @@ func BucketsViewHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
t, err := template.ParseFiles(l, p)
|
t, err := template.ParseFiles(l, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error parsing templates"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buckets, err := s3.ListBuckets()
|
buckets, err := s3.ListBuckets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error listing buckets"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.ExecuteTemplate(w, "layout", buckets)
|
err = t.ExecuteTemplate(w, "layout", buckets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error executing template"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,7 +37,7 @@ func TestBucketsViewHandler(t *testing.T) {
|
||||||
Err: errors.New("mocked S3 error"),
|
Err: errors.New("mocked S3 error"),
|
||||||
},
|
},
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBodyContains: "error listing buckets\n",
|
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,13 @@ func CreateBucketHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&bucket)
|
err := json.NewDecoder(r.Body).Decode(&bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error decoding json"
|
handleHTTPError(w, http.StatusUnprocessableEntity, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s3.MakeBucket(bucket.Name, "")
|
err = s3.MakeBucket(bucket.Name, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error making bucket"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +29,7 @@ func CreateBucketHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err = json.NewEncoder(w).Encode(bucket)
|
err = json.NewEncoder(w).Encode(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error encoding json"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,36 +14,36 @@ func TestCreateBucketHandler(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
s3 S3Client
|
s3 S3Client
|
||||||
body string
|
body string
|
||||||
expectedStatusCode int
|
expectedStatusCode int
|
||||||
expectedBody string
|
expectedBodyContains string
|
||||||
}{
|
}{
|
||||||
"success": {
|
"success": {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
body: "{\"name\":\"myBucket\"}",
|
body: "{\"name\":\"myBucket\"}",
|
||||||
expectedStatusCode: http.StatusCreated,
|
expectedStatusCode: http.StatusCreated,
|
||||||
expectedBody: "{\"name\":\"myBucket\",\"creationDate\":\"0001-01-01T00:00:00Z\"}\n",
|
expectedBodyContains: "{\"name\":\"myBucket\",\"creationDate\":\"0001-01-01T00:00:00Z\"}\n",
|
||||||
},
|
},
|
||||||
"empty request": {
|
"empty request": {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
body: "",
|
body: "",
|
||||||
expectedStatusCode: http.StatusUnprocessableEntity,
|
expectedStatusCode: http.StatusUnprocessableEntity,
|
||||||
expectedBody: "error decoding json\n",
|
expectedBodyContains: http.StatusText(http.StatusUnprocessableEntity),
|
||||||
},
|
},
|
||||||
"malformed request": {
|
"malformed request": {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
body: "}",
|
body: "}",
|
||||||
expectedStatusCode: http.StatusUnprocessableEntity,
|
expectedStatusCode: http.StatusUnprocessableEntity,
|
||||||
expectedBody: "error decoding json\n",
|
expectedBodyContains: http.StatusText(http.StatusUnprocessableEntity),
|
||||||
},
|
},
|
||||||
"s3 error": {
|
"s3 error": {
|
||||||
s3: &S3ClientMock{
|
s3: &S3ClientMock{
|
||||||
Err: errors.New("mocked S3 error"),
|
Err: errors.New("mocked S3 error"),
|
||||||
},
|
},
|
||||||
body: "{\"name\":\"myBucket\"}",
|
body: "{\"name\":\"myBucket\"}",
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBody: "error making bucket\n",
|
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,6 @@ func TestCreateBucketHandler(t *testing.T) {
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
|
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
|
||||||
assert.Equal(tc.expectedBody, rr.Body.String(), tcID)
|
assert.Contains(rr.Body.String(), tc.expectedBodyContains, tcID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,7 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err := json.NewDecoder(r.Body).Decode(©)
|
err := json.NewDecoder(r.Body).Decode(©)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error decoding json"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +36,7 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
|
||||||
objectSource := fmt.Sprintf("/%s/%s", copy.SourceBucketName, copy.SourceObjectName)
|
objectSource := fmt.Sprintf("/%s/%s", copy.SourceBucketName, copy.SourceObjectName)
|
||||||
err = s3.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds)
|
err = s3.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error copying object"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,30 +45,26 @@ func CreateObjectHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err = json.NewEncoder(w).Encode(copy)
|
err = json.NewEncoder(w).Encode(copy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error encoding json"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := r.ParseMultipartForm(32 << 20)
|
err := r.ParseMultipartForm(32 << 20)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error parsing form"
|
handleHTTPError(w, http.StatusUnprocessableEntity, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusUnprocessableEntity)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, handler, err := r.FormFile("file")
|
file, handler, err := r.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error getting form file"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
_, err = s3.PutObject(vars["bucketName"], handler.Filename, file, contentTypeOctetStream)
|
_, err = s3.PutObject(vars["bucketName"], handler.Filename, file, contentTypeOctetStream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error putting object"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ func DeleteBucketHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err := s3.RemoveBucket(vars["bucketName"])
|
err := s3.RemoveBucket(vars["bucketName"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error removing bucket"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,21 +13,21 @@ func TestDeleteBucketHandler(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
s3 S3Client
|
s3 S3Client
|
||||||
expectedStatusCode int
|
expectedStatusCode int
|
||||||
expectedBody string
|
expectedBodyContains string
|
||||||
}{
|
}{
|
||||||
"success": {
|
"success": {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
expectedStatusCode: http.StatusNoContent,
|
expectedStatusCode: http.StatusNoContent,
|
||||||
expectedBody: "",
|
expectedBodyContains: "",
|
||||||
},
|
},
|
||||||
"s3 error": {
|
"s3 error": {
|
||||||
s3: &S3ClientMock{
|
s3: &S3ClientMock{
|
||||||
Err: errors.New("mocked S3 error"),
|
Err: errors.New("mocked S3 error"),
|
||||||
},
|
},
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBody: "error removing bucket\n",
|
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,6 @@ func TestDeleteBucketHandler(t *testing.T) {
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
|
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
|
||||||
assert.Equal(tc.expectedBody, rr.Body.String(), tcID)
|
assert.Contains(rr.Body.String(), tc.expectedBodyContains, tcID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,7 @@ func DeleteObjectHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
err := s3.RemoveObject(vars["bucketName"], vars["objectName"])
|
err := s3.RemoveObject(vars["bucketName"], vars["objectName"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error removing object"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,21 +13,21 @@ func TestDeleteObjectHandler(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
s3 S3Client
|
s3 S3Client
|
||||||
expectedStatusCode int
|
expectedStatusCode int
|
||||||
expectedBody string
|
expectedBodyContains string
|
||||||
}{
|
}{
|
||||||
"success": {
|
"success": {
|
||||||
s3: &S3ClientMock{},
|
s3: &S3ClientMock{},
|
||||||
expectedStatusCode: http.StatusNoContent,
|
expectedStatusCode: http.StatusNoContent,
|
||||||
expectedBody: "",
|
expectedBodyContains: "",
|
||||||
},
|
},
|
||||||
"s3 error": {
|
"s3 error": {
|
||||||
s3: &S3ClientMock{
|
s3: &S3ClientMock{
|
||||||
Err: errors.New("mocked S3 error"),
|
Err: errors.New("mocked S3 error"),
|
||||||
},
|
},
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBody: "error removing object\n",
|
expectedBodyContains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,6 @@ func TestDeleteObjectHandler(t *testing.T) {
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
assert.Equal(tc.expectedStatusCode, rr.Code, tcID)
|
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
24
errors.go
Normal 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)
|
||||||
|
}
|
|
@ -16,8 +16,7 @@ func GetObjectHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
object, err := s3.GetObject(vars["bucketName"], objectName)
|
object, err := s3.GetObject(vars["bucketName"], objectName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error getting object"
|
handleHTTPError(w, http.StatusInternalServerError, err)
|
||||||
handleHTTPError(w, msg, err, http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,18 +25,11 @@ func GetObjectHandler(s3 S3Client) http.Handler {
|
||||||
|
|
||||||
_, err = io.Copy(w, object)
|
_, err = io.Copy(w, object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "error copying object"
|
|
||||||
code := http.StatusInternalServerError
|
code := http.StatusInternalServerError
|
||||||
if err.Error() == "The specified key does not exist." {
|
if err.Error() == ErrBucketDoesNotExist || err.Error() == ErrKeyDoesNotExist {
|
||||||
msg = "object not found"
|
|
||||||
code = http.StatusNotFound
|
code = http.StatusNotFound
|
||||||
}
|
}
|
||||||
if err.Error() == "The specified bucket does not exist." {
|
handleHTTPError(w, code, err)
|
||||||
msg = "bucket not found"
|
|
||||||
code = http.StatusNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHTTPError(w, msg, err, code)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestGetObjectHandler(t *testing.T) {
|
||||||
bucketName: "testBucket",
|
bucketName: "testBucket",
|
||||||
objectName: "testObject",
|
objectName: "testObject",
|
||||||
expectedStatusCode: http.StatusInternalServerError,
|
expectedStatusCode: http.StatusInternalServerError,
|
||||||
expectedBodyCountains: "error getting object\n",
|
expectedBodyCountains: http.StatusText(http.StatusInternalServerError),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue