mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 18:37:05 +00:00
reorganization of _examples and add some new examples such as iris+groupcache+mysql+docker
Former-commit-id: ed635ee95de7160cde11eaabc0c1dcb0e460a620
This commit is contained in:
130
_examples/database/mongodb/httputil/error.go
Normal file
130
_examples/database/mongodb/httputil/error.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package httputil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
var validStackFuncs = []func(string) bool{
|
||||
func(file string) bool {
|
||||
return strings.Contains(file, "/mongodb/api/")
|
||||
},
|
||||
}
|
||||
|
||||
// RuntimeCallerStack returns the app's `file:line` stacktrace
|
||||
// to give more information about an error cause.
|
||||
func RuntimeCallerStack() (s string) {
|
||||
var pcs [10]uintptr
|
||||
n := runtime.Callers(1, pcs[:])
|
||||
frames := runtime.CallersFrames(pcs[:n])
|
||||
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
for _, fn := range validStackFuncs {
|
||||
if fn(frame.File) {
|
||||
s += fmt.Sprintf("\n\t\t\t%s:%d", frame.File, frame.Line)
|
||||
}
|
||||
}
|
||||
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// HTTPError describes an HTTP error.
|
||||
type HTTPError struct {
|
||||
error
|
||||
Stack string `json:"-"` // the whole stacktrace.
|
||||
CallerStack string `json:"-"` // the caller, file:lineNumber
|
||||
When time.Time `json:"-"` // the time that the error occurred.
|
||||
// ErrorCode int: maybe a collection of known error codes.
|
||||
StatusCode int `json:"statusCode"`
|
||||
// could be named as "reason" as well
|
||||
// it's the message of the error.
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func newError(statusCode int, err error, format string, args ...interface{}) HTTPError {
|
||||
if format == "" {
|
||||
format = http.StatusText(statusCode)
|
||||
}
|
||||
|
||||
desc := fmt.Sprintf(format, args...)
|
||||
if err == nil {
|
||||
err = errors.New(desc)
|
||||
}
|
||||
|
||||
return HTTPError{
|
||||
err,
|
||||
string(debug.Stack()),
|
||||
RuntimeCallerStack(),
|
||||
time.Now(),
|
||||
statusCode,
|
||||
desc,
|
||||
}
|
||||
}
|
||||
|
||||
func (err HTTPError) writeHeaders(ctx iris.Context) {
|
||||
ctx.StatusCode(err.StatusCode)
|
||||
ctx.Header("X-Content-Type-Options", "nosniff")
|
||||
}
|
||||
|
||||
// LogFailure will print out the failure to the "logger".
|
||||
func LogFailure(logger io.Writer, ctx iris.Context, err HTTPError) {
|
||||
timeFmt := err.When.Format("2006/01/02 15:04:05")
|
||||
firstLine := fmt.Sprintf("%s %s: %s", timeFmt, http.StatusText(err.StatusCode), err.Error())
|
||||
whitespace := strings.Repeat(" ", len(timeFmt)+1)
|
||||
fmt.Fprintf(logger, "%s\n%sIP: %s\n%sURL: %s\n%sSource: %s\n",
|
||||
firstLine, whitespace, ctx.RemoteAddr(), whitespace, ctx.FullRequestURI(), whitespace, err.CallerStack)
|
||||
}
|
||||
|
||||
// Fail will send the status code, write the error's reason
|
||||
// and return the HTTPError for further use, i.e logging, see `InternalServerError`.
|
||||
func Fail(ctx iris.Context, statusCode int, err error, format string, args ...interface{}) HTTPError {
|
||||
httpErr := newError(statusCode, err, format, args...)
|
||||
httpErr.writeHeaders(ctx)
|
||||
|
||||
ctx.WriteString(httpErr.Description)
|
||||
return httpErr
|
||||
}
|
||||
|
||||
// FailJSON will send to the client the error data as JSON.
|
||||
// Useful for APIs.
|
||||
func FailJSON(ctx iris.Context, statusCode int, err error, format string, args ...interface{}) HTTPError {
|
||||
httpErr := newError(statusCode, err, format, args...)
|
||||
httpErr.writeHeaders(ctx)
|
||||
|
||||
ctx.JSON(httpErr)
|
||||
|
||||
return httpErr
|
||||
}
|
||||
|
||||
// InternalServerError logs to the server's terminal
|
||||
// and dispatches to the client the 500 Internal Server Error.
|
||||
// Internal Server errors are critical, so we log them to the `os.Stderr`.
|
||||
func InternalServerError(ctx iris.Context, err error, format string, args ...interface{}) {
|
||||
LogFailure(os.Stderr, ctx, Fail(ctx, iris.StatusInternalServerError, err, format, args...))
|
||||
}
|
||||
|
||||
// InternalServerErrorJSON acts exactly like `InternalServerError` but instead it sends the data as JSON.
|
||||
// Useful for APIs.
|
||||
func InternalServerErrorJSON(ctx iris.Context, err error, format string, args ...interface{}) {
|
||||
LogFailure(os.Stderr, ctx, FailJSON(ctx, iris.StatusInternalServerError, err, format, args...))
|
||||
}
|
||||
|
||||
// UnauthorizedJSON sends JSON format of StatusUnauthorized(401) HTTPError value.
|
||||
func UnauthorizedJSON(ctx iris.Context, err error, format string, args ...interface{}) HTTPError {
|
||||
return FailJSON(ctx, iris.StatusUnauthorized, err, format, args...)
|
||||
}
|
||||
Reference in New Issue
Block a user