package iris //taken from net/http const ( StatusContinue = 100 StatusSwitchingProtocols = 101 StatusOK = 200 StatusCreated = 201 StatusAccepted = 202 StatusNonAuthoritativeInfo = 203 StatusNoContent = 204 StatusResetContent = 205 StatusPartialContent = 206 StatusMultipleChoices = 300 StatusMovedPermanently = 301 StatusFound = 302 StatusSeeOther = 303 StatusNotModified = 304 StatusUseProxy = 305 StatusTemporaryRedirect = 307 StatusBadRequest = 400 StatusUnauthorized = 401 StatusPaymentRequired = 402 StatusForbidden = 403 StatusNotFound = 404 StatusMethodNotAllowed = 405 StatusNotAcceptable = 406 StatusProxyAuthRequired = 407 StatusRequestTimeout = 408 StatusConflict = 409 StatusGone = 410 StatusLengthRequired = 411 StatusPreconditionFailed = 412 StatusRequestEntityTooLarge = 413 StatusRequestURITooLong = 414 StatusUnsupportedMediaType = 415 StatusRequestedRangeNotSatisfiable = 416 StatusExpectationFailed = 417 StatusTeapot = 418 StatusPreconditionRequired = 428 StatusTooManyRequests = 429 StatusRequestHeaderFieldsTooLarge = 431 StatusUnavailableForLegalReasons = 451 StatusInternalServerError = 500 StatusNotImplemented = 501 StatusBadGateway = 502 StatusServiceUnavailable = 503 StatusGatewayTimeout = 504 StatusHTTPVersionNotSupported = 505 StatusNetworkAuthenticationRequired = 511 ) var statusText = map[int]string{ StatusContinue: "Continue", StatusSwitchingProtocols: "Switching Protocols", StatusOK: "OK", StatusCreated: "Created", StatusAccepted: "Accepted", StatusNonAuthoritativeInfo: "Non-Authoritative Information", StatusNoContent: "No Content", StatusResetContent: "Reset Content", StatusPartialContent: "Partial Content", StatusMultipleChoices: "Multiple Choices", StatusMovedPermanently: "Moved Permanently", StatusFound: "Found", StatusSeeOther: "See Other", StatusNotModified: "Not Modified", StatusUseProxy: "Use Proxy", StatusTemporaryRedirect: "Temporary Redirect", StatusBadRequest: "Bad Request", StatusUnauthorized: "Unauthorized", StatusPaymentRequired: "Payment Required", StatusForbidden: "Forbidden", StatusNotFound: "Not Found", StatusMethodNotAllowed: "Method Not Allowed", StatusNotAcceptable: "Not Acceptable", StatusProxyAuthRequired: "Proxy Authentication Required", StatusRequestTimeout: "Request Timeout", StatusConflict: "Conflict", StatusGone: "Gone", StatusLengthRequired: "Length Required", StatusPreconditionFailed: "Precondition Failed", StatusRequestEntityTooLarge: "Request Entity Too Large", StatusRequestURITooLong: "Request URI Too Long", StatusUnsupportedMediaType: "Unsupported Media Type", StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable", StatusExpectationFailed: "Expectation Failed", StatusTeapot: "I'm a teapot", StatusPreconditionRequired: "Precondition Required", StatusTooManyRequests: "Too Many Requests", StatusRequestHeaderFieldsTooLarge: "Request Header Fields Too Large", StatusUnavailableForLegalReasons: "Unavailable For Legal Reasons", StatusInternalServerError: "Internal Server Error", StatusNotImplemented: "Not Implemented", StatusBadGateway: "Bad Gateway", StatusServiceUnavailable: "Service Unavailable", StatusGatewayTimeout: "Gateway Timeout", StatusHTTPVersionNotSupported: "HTTP Version Not Supported", StatusNetworkAuthenticationRequired: "Network Authentication Required", } // StatusText returns a text for the HTTP status code. It returns the empty // string if the code is unknown. func StatusText(code int) string { return statusText[code] } // type ( // HTTPErrorHandler is just an object which stores a http status code and a handler HTTPErrorHandler struct { code int handler HandlerFunc } // HTTPErrorContainer is the struct which contains the handlers which will execute if http error occurs // One struct per Server instance, the meaning of this is that the developer can change the default error message and replace them with his/her own completely custom handlers // // Example of usage: // iris.OnError(405, func (ctx *iris.Context){ c.SendStatus(405,"Method not allowed!!!")}) // and inside the handler which you have access to the current Context: // ctx.EmitError(405) HTTPErrorContainer struct { // Errors contains all the httperrorhandlers Errors []*HTTPErrorHandler } ) // HTTPErrorHandlerFunc creates a handler which is responsible to send a particular error to the client func HTTPErrorHandlerFunc(statusCode int, message string) HandlerFunc { return func(ctx *Context) { ctx.SetStatusCode(statusCode) ctx.SetBodyString(message) } } // GetCode returns the http status code value func (e *HTTPErrorHandler) GetCode() int { return e.code } // GetHandler returns the handler which is type of HandlerFunc func (e *HTTPErrorHandler) GetHandler() HandlerFunc { return e.handler } // SetHandler sets the handler (type of HandlerFunc) to this particular ErrorHandler func (e *HTTPErrorHandler) SetHandler(h HandlerFunc) { e.handler = h } // defaultHTTPErrors creates and returns an instance of HTTPErrorContainer with default handlers func defaultHTTPErrors() *HTTPErrorContainer { httperrors := new(HTTPErrorContainer) httperrors.Errors = make([]*HTTPErrorHandler, 0) httperrors.OnError(StatusNotFound, HTTPErrorHandlerFunc(StatusNotFound, statusText[StatusNotFound])) httperrors.OnError(StatusInternalServerError, HTTPErrorHandlerFunc(StatusInternalServerError, statusText[StatusInternalServerError])) return httperrors } // GetByCode returns the error handler by it's http status code func (he *HTTPErrorContainer) GetByCode(httpStatus int) *HTTPErrorHandler { if he != nil { for _, h := range he.Errors { if h.GetCode() == httpStatus { return h } } } return nil } // OnError Registers a handler for a specific http error status func (he *HTTPErrorContainer) OnError(httpStatus int, handler HandlerFunc) { if httpStatus == StatusOK { return } if errH := he.GetByCode(httpStatus); errH != nil { errH.SetHandler(handler) } else { he.Errors = append(he.Errors, &HTTPErrorHandler{code: httpStatus, handler: handler}) } } ///TODO: the errors must have .Next too, as middlewares inside the Context, if I let it as it is then we have problem // we cannot set a logger and a custom handler at one error because now the error handler takes only one handelrFunc and executes there from here... // EmitError executes the handler of the given error http status code func (he *HTTPErrorContainer) EmitError(errCode int, ctx *Context) { ctx.ResetBody() if errHandler := he.GetByCode(errCode); errHandler != nil { ctx.SetStatusCode(errCode) // for any case, user can change it after if want to errHandler.GetHandler().Serve(ctx) } else { //if no error is registed, then register it with the default http error text, and re-run the Emit he.OnError(errCode, func(c *Context) { c.SetStatusCode(errCode) c.SetBodyString(StatusText(errCode)) }) he.EmitError(errCode, ctx) } } // OnNotFound sets the handler for http status 404, // default is a response with text: 'Not Found' and status: 404 func (he *HTTPErrorContainer) OnNotFound(handlerFunc HandlerFunc) { he.OnError(StatusNotFound, handlerFunc) } // OnPanic sets the handler for http status 500, // default is a response with text: The server encountered an unexpected condition which prevented it from fulfilling the request. and status: 500 func (he *HTTPErrorContainer) OnPanic(handlerFunc HandlerFunc) { he.OnError(StatusInternalServerError, handlerFunc) }