Skip to content

Commit

Permalink
Added to echo_service_extensions to handle errors on echo and refacto…
Browse files Browse the repository at this point in the history
…ring common code blocks
  • Loading branch information
rozturac committed Dec 5, 2021
1 parent 7248a0d commit f65db5e
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 37 deletions.
38 changes: 38 additions & 0 deletions _examples/cmd/echo_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/rozturac/cerror"
"github.com/rozturac/cerror/extensions"
"net/http"
)

type EchoErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
}

func main() {
e := echo.New()
e.Use(extensions.AddEchoErrorHandlingMiddlewareWithMapper(func(errorCode, message string, httpStatusCode int) interface{} {
return EchoErrorResponse{
Code: errorCode,
Message: message,
}
}))

e.Use(middleware.CORS())

e.GET("/example", example)

e.Start(":8080")
}

func example(c echo.Context) error {
if name := c.Param("Name"); len(name) == 0 {
panic(cerror.NullReferenceError("name"))
}

return c.String(http.StatusOK, "Hello, World!")
}
3 changes: 2 additions & 1 deletion _examples/cmd/http_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"github.com/rozturac/cerror"
"github.com/rozturac/cerror/extensions"
"net/http"
)

Expand All @@ -22,6 +23,6 @@ func main() {
}
}

http.Handle("/example", cerror.AddErrorHandlingMiddlewareWithMapper(handler, mapper))
http.Handle("/example", extensions.AddHttpErrorHandlingMiddlewareWithMapper(handler, mapper))
http.ListenAndServe(":8080", nil)
}
24 changes: 24 additions & 0 deletions extensions/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package extensions

import (
"github.com/rozturac/cerror"
"net/http"
)

type ErrorResponseMapper func(errorCode, message string, httpStatusCode int) interface{}

func getErrorResponseAndStatusCode(candidateError interface{}, mapper ErrorResponseMapper) (interface{}, int) {
response := mapper("UnExpectedError", http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
httpStatusCode := http.StatusInternalServerError

if err, ok := candidateError.(error); ok {
if customError, ok := err.(cerror.Error); ok {
response = mapper(customError.ErrorCode(), customError.Error(), customError.HttpStatusCode())
httpStatusCode = customError.HttpStatusCode()
} else {
response = mapper("UnExpectedError", err.Error(), http.StatusInternalServerError)
}
}

return response, httpStatusCode
}
32 changes: 32 additions & 0 deletions extensions/echo_service_extensions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package extensions

import (
"github.com/labstack/echo/v4"
"net/http"
)

func AddEchoErrorHandlingMiddlewareWithMapper(mapper ErrorResponseMapper) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(context echo.Context) error {
defer func() {
if recover := recover(); recover != nil {
response, httpStatusCode := getErrorResponseAndStatusCode(recover, mapper)
if err := context.JSON(httpStatusCode, response); err != nil {
context.NoContent(http.StatusInternalServerError)
}
} else {
context.NoContent(http.StatusInternalServerError)
}
}()

if err := next(context); err != nil {
response, httpStatusCode := getErrorResponseAndStatusCode(err, mapper)
if err := context.JSON(httpStatusCode, response); err != nil {
context.NoContent(http.StatusInternalServerError)
}
}

return nil
}
}
}
25 changes: 25 additions & 0 deletions extensions/http_service_extensions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package extensions

import (
"encoding/json"
"net/http"
)

func AddHttpErrorHandlingMiddlewareWithMapper(next http.HandlerFunc, mapper ErrorResponseMapper) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
defer func() {
if recover := recover(); recover != nil {
response, httpStatusCode := getErrorResponseAndStatusCode(recover, mapper)
if buff, err := json.Marshal(response); err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
} else {
http.Error(writer, string(buff), httpStatusCode)
}
} else {
http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
}()

next(writer, request)
}
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/rozturac/cerror

go 1.16
go 1.16

require github.com/labstack/echo/v4 v4.6.1 // indirect
35 changes: 0 additions & 35 deletions http_service_extensions.go

This file was deleted.

0 comments on commit f65db5e

Please sign in to comment.