diff --git a/internal/server/control/control_test.go b/internal/server/control/control_test.go
index c40b70b..9d1738d 100644
--- a/internal/server/control/control_test.go
+++ b/internal/server/control/control_test.go
@@ -130,7 +130,7 @@ func TestAddRouteReturnsBadRequestWhenMalformedJSONBody(t *testing.T) {
addRoute(resp, req)
for _, e := range checkErrorResponse(resp.Result(), http.StatusBadRequest, "Malformed JSON") {
- t.Error(e.Error())
+ t.Error(e)
}
}
@@ -194,7 +194,7 @@ func TestAddRouteReturns422ErrorWhenMandatoryFieldsMissing(t *testing.T) {
r := resp.Result()
if test.testMustFail {
for _, e := range checkErrorResponse(r, http.StatusUnprocessableEntity, "Invalid Route") {
- t.Error(e.Error())
+ t.Error(e)
}
} else if !test.testMustFail {
if r.StatusCode != http.StatusCreated {
@@ -258,7 +258,7 @@ func TestAddRoute500sWhenIDGeneratorFails(t *testing.T) {
addRoute(resp, req)
for _, e := range checkErrorResponse(resp.Result(), http.StatusInternalServerError, "Internal Server Error") {
- t.Error(e.Error())
+ t.Error(e)
}
}
@@ -324,7 +324,7 @@ func TestAddRoute422sWhenInvalidRoute(t *testing.T) {
addRoute(resp, req)
for _, e := range checkErrorResponse(resp.Result(), http.StatusUnprocessableEntity, "Invalid Route") {
- t.Error(e.Error())
+ t.Error(e)
}
}
@@ -345,7 +345,7 @@ func TestRemoveRouteReturnsNotFound(t *testing.T) {
handler.ServeHTTP(resp, req)
for _, e := range checkErrorResponse(resp.Result(), http.StatusNotFound, "Route Not Found") {
- t.Error(e.Error())
+ t.Error(e)
}
}
@@ -436,7 +436,7 @@ func TestGetRouteReturns404sWhenRouteDoesntExist(t *testing.T) {
handler.ServeHTTP(w, r)
for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Route Not Found") {
- t.Error(e.Error())
+ t.Error(e)
}
}
diff --git a/internal/server/data/decorator_test.go b/internal/server/data/decorator_test.go
index 420b7bb..1c75cdd 100644
--- a/internal/server/data/decorator_test.go
+++ b/internal/server/data/decorator_test.go
@@ -128,7 +128,7 @@ func TestCheckHandlerReturnsAFunctionsThat404sWhenHandlerDoesNotExist(t *testing
fn(w, r)
for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Handler ID Not Found") {
- t.Error(e.Error())
+ t.Error(e)
}
}
diff --git a/internal/server/data/resource.go b/internal/server/data/resource.go
index caf3e13..d55fc72 100644
--- a/internal/server/data/resource.go
+++ b/internal/server/data/resource.go
@@ -28,12 +28,18 @@ import (
"github.com/gorilla/mux"
)
+const (
+ ResourceItemNotFound = "Resource Item Not Found"
+ NonIntegerValue = "Non Integer Value"
+ InvalidStatusCode = "Invalid Status Code"
+)
+
func getRequestBody(w http.ResponseWriter, r *http.Request, h *model.Handler) {
w.Header().Add("Content-Type", "application/octet-stream")
n, err := io.Copy(w, h.Request.Body)
if err != nil {
if n == 0 {
- srverrors.WriteErrorResponse(http.StatusInternalServerError, "Internal Server Error", w)
+ srverrors.WriteErrorResponse(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), w)
} else {
// Only way to abort current connection as of go 1.13
// https://github.com/golang/go/issues/16542
@@ -65,7 +71,7 @@ func getRequestMatches(w http.ResponseWriter, r *http.Request, h *model.Handler)
if value, ok := vars[name]; ok {
_, _ = w.Write([]byte(value))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -75,7 +81,7 @@ func getRequestParams(w http.ResponseWriter, r *http.Request, h *model.Handler)
if values, ok := h.Request.URL.Query()[name]; ok {
_, _ = w.Write([]byte(values[0]))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -85,7 +91,7 @@ func getRequestHeaders(w http.ResponseWriter, r *http.Request, h *model.Handler)
if values, ok := h.Request.Header[textproto.CanonicalMIMEHeaderKey(name)]; ok {
_, _ = w.Write([]byte(values[0]))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -95,7 +101,7 @@ func getRequestCookies(w http.ResponseWriter, r *http.Request, h *model.Handler)
if cookie, err := h.Request.Cookie(name); err == nil {
_, _ = w.Write([]byte(cookie.Value))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -111,11 +117,11 @@ func getRequestForm(w http.ResponseWriter, r *http.Request, h *model.Handler) {
// We tried to exercise this execution path but didn't know how.
err := h.Request.ParseForm()
if err != nil {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
} else if values, ok := h.Request.Form[name]; ok {
_, _ = w.Write([]byte(values[0]))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -126,7 +132,7 @@ func getRequestFileName(w http.ResponseWriter, r *http.Request, h *model.Handler
if err == nil {
_, _ = w.Write([]byte(header.Filename))
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -137,7 +143,7 @@ func getRequestFileContent(w http.ResponseWriter, r *http.Request, h *model.Hand
if err == nil {
_, _ = io.Copy(w, file)
} else {
- w.WriteHeader(http.StatusNotFound)
+ srverrors.WriteErrorResponse(http.StatusNotFound, ResourceItemNotFound, w)
}
}
@@ -146,17 +152,16 @@ func getRequestFileContent(w http.ResponseWriter, r *http.Request, h *model.Hand
func setResponseStatus(w http.ResponseWriter, r *http.Request, h *model.Handler) {
sb, err := ioutil.ReadAll(r.Body)
if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
+ srverrors.WriteErrorResponse(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), w)
return
}
- si, err := strconv.Atoi(string(sb))
- if http.StatusText(si) == "" {
- w.WriteHeader(http.StatusBadRequest)
- } else if err == nil {
- h.Writer.WriteHeader(int(si))
+ if si, err := strconv.Atoi(string(sb)); err != nil {
+ srverrors.WriteErrorResponse(http.StatusUnprocessableEntity, NonIntegerValue, w)
+ } else if http.StatusText(si) == "" {
+ srverrors.WriteErrorResponse(http.StatusBadRequest, InvalidStatusCode, w)
} else {
- w.WriteHeader(http.StatusBadRequest)
+ h.Writer.WriteHeader(int(si))
}
}
@@ -164,7 +169,7 @@ func setResponseHeaders(w http.ResponseWriter, r *http.Request, h *model.Handler
name := mux.Vars(r)["name"]
vb, err := ioutil.ReadAll(r.Body)
if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
+ srverrors.WriteErrorResponse(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), w)
return
}
@@ -180,7 +185,7 @@ func setResponseCookies(w http.ResponseWriter, r *http.Request, h *model.Handler
name := mux.Vars(r)["name"]
vb, err := ioutil.ReadAll(r.Body)
if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
+ srverrors.WriteErrorResponse(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), w)
return
}
@@ -193,6 +198,6 @@ func setResponseBody(w http.ResponseWriter, r *http.Request, h *model.Handler) {
if n > 0 {
panic("Truncated body")
}
- w.WriteHeader(http.StatusInternalServerError)
+ srverrors.WriteErrorResponse(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), w)
}
}
diff --git a/internal/server/data/resource_test.go b/internal/server/data/resource_test.go
index 73e7c32..7ed8fae 100644
--- a/internal/server/data/resource_test.go
+++ b/internal/server/data/resource_test.go
@@ -121,8 +121,8 @@ func TestGetRequestBody500sWhenHandlerRequestErrors(t *testing.T) {
getRequestBody(w, r, &h)
- for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, "Internal Server Error") {
- t.Error(e.Error())
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
@@ -369,9 +369,8 @@ func TestGetRequestMatchesReturnsNotFoundWhenMatchDoesntExists(t *testing.T) {
getRequestMatches(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404. Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -433,9 +432,8 @@ func TestGetRequestParams404sWhenParamDoesntExist(t *testing.T) {
getRequestParams(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404. Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -478,14 +476,15 @@ func TestGetRequestHeadersSetsOctectStreamContentType(t *testing.T) {
Request: httptest.NewRequest("GET", "/", nil),
Writer: httptest.NewRecorder(),
}
+ h.Request.Header.Set("bar", "BAZ")
r := createMuxRequest("/handlers/HANDLERID/request/headers/{name}", "/handlers/HANDLERID/request/headers/bar", "GET", nil)
w := httptest.NewRecorder()
getRequestHeaders(w, r, &h)
res := w.Result()
- if res.Header.Get("Content-Type") != "application/octet-stream" {
- t.Error("Content Type mismatch")
+ if v := res.Header.Get("Content-Type"); v != "application/octet-stream" {
+ t.Errorf("Content Type mismatch. Expected: application/octet-stream. Got: %q", v)
}
}
@@ -567,9 +566,8 @@ func TestGetRequestHeaders404sWhenHeaderDoesntExist(t *testing.T) {
getRequestHeaders(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Error("Status code mismatch")
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -652,9 +650,8 @@ func TestGetRequestCookies404sIfCookieDoesntExist(t *testing.T) {
getRequestCookies(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -754,9 +751,8 @@ func TestGetRequestForm404sWhenFieldDoesntExist(t *testing.T) {
getRequestForm(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -810,9 +806,8 @@ func TestGetRequestForm404sWhenFormDoesntExist(t *testing.T) {
getRequestForm(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -885,9 +880,8 @@ func TestGetRequestFileName404sWhenFileDoesntExist(t *testing.T) {
getRequestFileName(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -902,9 +896,8 @@ func TestGetRequestFileName404sWhenFormDoesntExist(t *testing.T) {
getRequestFileName(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -966,9 +959,8 @@ func TestGetRequestFileContent404sWhenFileDoesntExist(t *testing.T) {
getRequestFileContent(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -983,9 +975,8 @@ func TestGetRequestFileContent404sWhenFormDoesntExist(t *testing.T) {
getRequestFileContent(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusNotFound {
- t.Errorf("Status code mismatch. Expected: 404, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusNotFound, "Resource Item Not Found") {
+ t.Error(e)
}
}
@@ -1009,9 +1000,8 @@ func TestGetRequestFileContent500sWhenHandlerRequestErrors(t *testing.T) {
getRequestFileContent(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusInternalServerError {
- t.Error("status not 500", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
@@ -1058,9 +1048,8 @@ func TestSetResponseStatus400sWhenNonparseableStatusCode(t *testing.T) {
setResponseStatus(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusBadRequest {
- t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusUnprocessableEntity, "Non Integer Value") {
+ t.Error(e)
}
}
@@ -1074,9 +1063,8 @@ func TestSetResponseStatus500sWhenErrorReadingRequest(t *testing.T) {
setResponseStatus(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusInternalServerError {
- t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
@@ -1092,9 +1080,8 @@ func TestSetResponseStatus400sWhenStatusCodeNotSupportedByGo(t *testing.T) {
setResponseStatus(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusBadRequest {
- t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusBadRequest, "Invalid Status Code") {
+ t.Error(e)
}
}
@@ -1162,9 +1149,8 @@ func TestSetResponseHeaders500sWhenErrorReadingRequest(t *testing.T) {
setResponseHeaders(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusInternalServerError {
- t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
@@ -1181,9 +1167,8 @@ func TestSetResponseHeaders400sOnInvalidHeaderKey(t *testing.T) {
setResponseHeaders(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusBadRequest {
- t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusBadRequest, "Invalid Header Name") {
+ t.Error(e)
}
}
@@ -1200,9 +1185,8 @@ func TestSetResponseHeaders400sOnInvalidHeaderValue(t *testing.T) {
setResponseHeaders(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusBadRequest {
- t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusBadRequest, "Invalid Header Value") {
+ t.Error(e)
}
}
@@ -1250,9 +1234,8 @@ func TestSetResponseCookies500sWhenErrorReadingRequest(t *testing.T) {
setResponseCookies(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusInternalServerError {
- t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
@@ -1322,9 +1305,8 @@ func TestSetResponseBody500sWhenReaderFailsInFirstRead(t *testing.T) {
setResponseBody(w, r, &h)
- res := w.Result()
- if res.StatusCode != http.StatusInternalServerError {
- t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode)
+ for _, e := range checkErrorResponse(w.Result(), http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) {
+ t.Error(e)
}
}
diff --git a/internal/server/data/server_test.go b/internal/server/data/server_test.go
index 30cadf5..7481e5a 100644
--- a/internal/server/data/server_test.go
+++ b/internal/server/data/server_test.go
@@ -78,6 +78,6 @@ func TestConfigRouterReturnsRouterThat400sOnUnconfiguredResources(t *testing.T)
m.ServeHTTP(w, httptest.NewRequest("GET", "/handlers/FOO/dummy", nil))
for _, e := range checkErrorResponse(w.Result(), http.StatusBadRequest, "Invalid Resource Path") {
- t.Error(e.Error())
+ t.Error(e)
}
}
diff --git a/spec/README.md b/spec/README.md
index ba95891..aadca97 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -554,6 +554,10 @@ path doesn't exist or is invalid.
* **Error Responses**:
* **Code**: `400`; Reason: `Invalid Resource Path`
**Notes**: Check the list of valid resource paths at the top of this section.
+ * **Code**: `422`; Reason: `Non Integer Value`
+ **Notes**: When setting the status code with a non integer value.
+ * **Code**: `400`; Reason: `Invalid Status Code`
+ **Notes**: When setting a non-supported status code.
* **Code**: `404`; Reason: `Handler ID Not Found`
**Notes**: Refers to the handler resource itself.
* **Sample Call**: