Index: appengine/ephelper/epfrontend/error.go |
diff --git a/appengine/ephelper/epfrontend/error.go b/appengine/ephelper/epfrontend/error.go |
deleted file mode 100644 |
index b77a2ea01f992602e51533ae19d4ad0ab5367024..0000000000000000000000000000000000000000 |
--- a/appengine/ephelper/epfrontend/error.go |
+++ /dev/null |
@@ -1,184 +0,0 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-package epfrontend |
- |
-import ( |
- "bytes" |
- "encoding/json" |
- "fmt" |
- "net/http" |
- |
- "github.com/GoogleCloudPlatform/go-endpoints/endpoints" |
-) |
- |
-type outerError struct { |
- Error *innerError `json:"error"` |
-} |
- |
-type innerError struct { |
- Code int `json:"code"` |
- Errors []*errorInstance `json:"errors"` |
- Message string `json:"message"` |
-} |
- |
-type errorInstance struct { |
- Domain string `json:"domain"` |
- Message string `json:"message"` |
- Reason string `json:"reason"` |
-} |
- |
-// endpointsErrorResponse is a copy of go-endpoints' errorResponse struct. |
-type endpointsErrorResponse struct { |
- // Currently always "APPLICATION_ERROR" |
- State string `json:"state"` |
- Name string `json:"error_name"` |
- Msg string `json:"error_message,omitempty"` |
- Code int `json:"-"` |
-} |
- |
-// errorResponseWriter is an http.ResponseWriter implementation that captures |
-// endpoints errors that are written to it and emits them as error JSON. |
-// |
-// This fulfills the purpose of collecting an error response, generated either |
-// by the frontend processing code (e.g., could not find method) or the backend |
-// handling code (e.g., endpoint returned an error, JSON unmarshal, etc.) and |
-// boxing it into a frontend error response structure. |
-// |
-// If the frontend handler encounters an error, it will be set via setError. |
-// |
-// If the backend code generates an error, it will be captured as follows: |
-// 1) The backend will invoke WriteHeader with an error status. That will enable |
-// response buffering. |
-// 2) Write will be called to write out the backend error response JSON. This |
-// will be captured for deconstruction. |
-// |
-// In either case, the error state will be forwarded to the real underlying |
-// ResponseWriter via forwardError. If no error is assigned, all operations |
-// essentially pass through to the underlying ResponseWriter, making this very |
-// low overhead in the standard case. |
-type errorResponseWriter struct { |
- http.ResponseWriter |
- |
- status int |
- inst *errorInstance |
- buf bytes.Buffer |
-} |
- |
-func (w *errorResponseWriter) WriteHeader(status int) { |
- if w.status != 0 { |
- return |
- } |
- |
- // If we have an error status (>= 400) |
- w.status = status |
- if w.status >= http.StatusBadRequest { |
- w.status, w.inst = w.translateReason(status) |
- } |
- w.ResponseWriter.WriteHeader(w.status) |
-} |
- |
-func (w *errorResponseWriter) Write(d []byte) (int, error) { |
- // If we have an error status. |
- if w.inst != nil { |
- return w.buf.Write(d) |
- } |
- return w.ResponseWriter.Write(d) |
-} |
- |
-// setError explicitly configures an error response. |
-// |
-// This is used by the frontend ServeHTTP code when an error is encountered |
-// prior to calling into the backend. If the backend is invoked, setError will |
-// not be called. |
-func (w *errorResponseWriter) setError(err error) { |
- e, ok := err.(*endpoints.APIError) |
- if !ok { |
- e = &endpoints.APIError{ |
- Msg: err.Error(), |
- Code: http.StatusInternalServerError, |
- } |
- } |
- w.WriteHeader(e.Code) |
- w.inst.Message = err.Error() |
-} |
- |
-func (w *errorResponseWriter) forwardError() bool { |
- if w.inst == nil { |
- // No buffered error; leave things be. |
- return false |
- } |
- |
- ierr := innerError{ |
- Code: w.status, |
- Message: "unspecified error", |
- Errors: []*errorInstance{w.inst}, |
- } |
- if w.inst.Message == "" { |
- // Attempt to load the message from the backend endpoints error JSON. |
- if w.buf.Len() > 0 { |
- resp := endpointsErrorResponse{} |
- if err := json.NewDecoder(&w.buf).Decode(&resp); err != nil { |
- w.inst.Message = fmt.Sprintf("Failed to decode error JSON (%s): %s", err, w.buf.String()) |
- } else { |
- w.inst.Message = resp.Msg |
- ierr.Message = resp.Msg |
- } |
- } |
- } |
- |
- feErr := outerError{ |
- Error: &ierr, |
- } |
- data, err := json.MarshalIndent(feErr, "", " ") |
- if err != nil { |
- return true |
- } |
- w.ResponseWriter.Write(data) |
- return true |
-} |
- |
-// translateReason returns an errorInstance populated from an HTTP status. |
-// |
-// The mappings here are copied from Python AppEngine: |
-// /google/appengine/tools/devappserver2/endpoints/generated_error_info.py |
-func (*errorResponseWriter) translateReason(status int) (int, *errorInstance) { |
- code := status |
- r := errorInstance{ |
- Domain: "global", |
- } |
- switch status { |
- case 400: |
- r.Reason = "badRequest" |
- case 401: |
- r.Reason = "required" |
- case 402: |
- r.Reason = "unsupportedProtocol" |
- case 403: |
- r.Reason = "forbidden" |
- case 404: |
- r.Reason = "notFound" |
- case 405: |
- r.Reason = "unsupportedMethod" |
- case 409: |
- r.Reason = "conflict" |
- case 410: |
- r.Reason = "deleted" |
- case 412: |
- r.Reason = "conditionNotMet" |
- case 413: |
- r.Reason = "uploadTooLarge" |
- |
- case 406, 407, 411, 414, 415, 416, 417: |
- code = 404 |
- r.Reason = "unsupportedProtocol" |
- |
- case 408: |
- fallthrough |
- default: |
- code = 503 |
- r.Reason = "backendError" |
- } |
- return code, &r |
-} |