| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package module
- import (
- "encoding/json"
- "errors"
- "fmt"
- "log"
- "net/http"
- "runtime"
- )
- // Err... are errors used globally
- var (
- ErrUnknown = errors.New("Unknown error")
- // ErrRetrievingImage = errors.New("Error retrieving image")
- // ErrInvalidURL = errors.New("Passed URL is not valid")
- // ErrDecodingImage = errors.New("Error decoding image")
- // ErrWidthNoInteger = errors.New("Error parsing width parameter as integer")
- // ErrHeightNoInteger = errors.New("Error parsing height parameter as integer")
- // ErrAspectRatioWidthNoInteger = errors.New("Error parsing aspect ratio width parameter as integer")
- // ErrAspectRatioHeightNoInteger = errors.New("Error parsing aspect ratio height parameter as integer")
- ErrReadingRequestBody = errors.New("Error reading request body")
- ErrDecodingJSON = errors.New("Error decoding JSON")
- // ErrDecodingBase64 = errors.New("Error decoding base64 encoded image")
- // ErrReadingCroppedImage = errors.New("Error reading cropped image")
- // ErrCreatingThumbnail = errors.New("Error creating thumbnail")
- // ErrDecodingImageInternal = errors.New("Error decoding image")
- // ErrEncodingImage = errors.New("Error encoding image")
- ErrSendingResponse = errors.New("Error sending response")
- ErrEncodingJSON = errors.New("Error encoding JSON")
- ErrDatabase = errors.New("Database error")
- ErrRetrievingTestData = errors.New("Error receiving Testdata")
- ErrParsingInt = errors.New("Error parsing string to int")
- ErrReadingFile = errors.New("Error reading file")
- )
- // StatusCodeMapper maps errors to HTTP Status codes
- var StatusCodeMapper = map[error]int{
- ErrUnknown: http.StatusInternalServerError,
- // ErrRetrievingImage: http.StatusBadRequest,
- // ErrInvalidURL: http.StatusBadRequest,
- // ErrDecodingImage: http.StatusBadRequest,
- // ErrWidthNoInteger: http.StatusBadRequest,
- // ErrHeightNoInteger: http.StatusBadRequest,
- // ErrAspectRatioWidthNoInteger: http.StatusBadRequest,
- // ErrAspectRatioHeightNoInteger: http.StatusBadRequest,
- ErrReadingRequestBody: http.StatusBadRequest,
- ErrDecodingJSON: http.StatusBadRequest,
- // ErrDecodingBase64: http.StatusBadRequest,
- // ErrReadingCroppedImage: http.StatusInternalServerError,
- // ErrCreatingThumbnail: http.StatusInternalServerError,
- // ErrDecodingImageInternal: http.StatusInternalServerError,
- // ErrEncodingImage: http.StatusInternalServerError,
- ErrSendingResponse: http.StatusInternalServerError,
- ErrEncodingJSON: http.StatusInternalServerError,
- ErrDatabase: http.StatusInternalServerError,
- ErrRetrievingTestData: http.StatusBadGateway,
- ErrParsingInt: http.StatusInternalServerError,
- ErrReadingFile: http.StatusInternalServerError,
- }
- // MetaError is two errors in one
- type MetaError struct {
- outerError error
- innerError error
- httpStatus int
- }
- // NewMetaError returns a new MetaError and automatically selects the suited HTTP Status Code
- func NewMetaError(outerError error, innerError error) MetaError {
- return MetaError{outerError, innerError, StatusCodeMapper[outerError]}
- }
- // NewMetaErrorWithStatus returns a new MetaError with manually selected HTTP Status Code
- func NewMetaErrorWithStatus(outerError error, innerError error, httpStatus int) MetaError {
- return MetaError{outerError, innerError, httpStatus}
- }
- func (err MetaError) Error() string {
- return err.outerError.Error() + ": " + err.innerError.Error()
- }
- type StatusError struct {
- error
- httpStatus int
- }
- func NewStatusError(err error, status int) StatusError {
- return StatusError{err, status}
- }
- // HandleError will handle errors
- func HandleError(outerErr error, innerErr error) {
- if innerErr != nil {
- switch outerErr {
- case ErrDatabase:
- switch innerErr.Error() {
- case "record not found":
- panic(NewStatusError(innerErr, http.StatusNotFound))
- }
- }
- panic(NewMetaError(outerErr, innerErr))
- }
- }
- // HTTPStatusHandler ...
- type HTTPStatusHandler struct {
- Debug bool // TODO implement
- }
- // NewHTTPStatusHandler ...
- func NewHTTPStatusHandler() *HTTPStatusHandler {
- return &HTTPStatusHandler{
- Debug: false,
- }
- }
- // HTTPStatusRecovery catches errors and serves http statuses
- func (rec *HTTPStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
- defer func() {
- if err := recover(); err != nil {
- // get the stack traces and print it out
- // stack := stack(0)
- // log.Printf("PANIC: %s\n%s", err, stack)
- // convert err to a string
- var errMsg string
- if e, ok := err.(error); ok {
- errMsg = e.Error()
- } else {
- errMsg = fmt.Sprint(err)
- }
- // Logging
- _, file, line, _ := runtime.Caller(4)
- log.Printf("%s:%d: %s", file, line, errMsg)
- errText, jErr := json.Marshal(map[string]string{"status": errMsg})
- if jErr != nil {
- log.Println(jErr)
- // TODO handle error
- }
- if _, ok := err.(MetaError); ok {
- http.Error(w, string(errText), err.(MetaError).httpStatus)
- } else if _, ok = err.(StatusError); ok {
- http.Error(w, string(errText), err.(StatusError).httpStatus)
- } else {
- http.Error(w, string(errText), http.StatusInternalServerError)
- }
- }
- }()
- next(w, r)
- }
- // Log logs
- func Log(text string) {
- log.Println(text)
- }
|