github.com/influx6/npkg@v0.8.8/nhttp/http.go (about) 1 package nhttp 2 3 import ( 4 "encoding/base64" 5 "errors" 6 "io" 7 "mime" 8 "net/http" 9 "path/filepath" 10 "strings" 11 12 "github.com/influx6/npkg" 13 "github.com/influx6/npkg/njson" 14 ) 15 16 const ( 17 maxsize = 32 << 40 18 19 // MultipartKey defines the key used to store multipart Form. 20 MultipartKey = "MultiPartForm" 21 ) 22 23 // HTTPError defines custom error that can be used to specify 24 // status code and message. 25 type HTTPError struct { 26 Code int 27 Err error 28 } 29 30 // Error returns error string. Implements error interface. 31 func (h HTTPError) Error() string { 32 return h.Err.Error() 33 } 34 35 // Gzip Compression 36 type gzipResponseWriter struct { 37 io.Writer 38 http.ResponseWriter 39 } 40 41 func (w gzipResponseWriter) Write(b []byte) (int, error) { 42 return w.Writer.Write(b) 43 } 44 45 // handlerImpl implements http.Handler interface. 46 type handlerImpl struct { 47 ContextHandler 48 } 49 50 // ServeHTTP implements http.Handler.ServeHttp method. 51 func (h handlerImpl) ServeHTTP(w http.ResponseWriter, r *http.Request) { 52 ctx := NewContext(SetRequest(r), SetResponseWriter(w)) 53 if err := ctx.InitForms(); err != nil { 54 http.Error(w, err.Error(), http.StatusBadRequest) 55 return 56 } 57 58 defer ctx.ClearFlashMessages() 59 60 if err := h.ContextHandler(ctx); err != nil { 61 if httperr, ok := err.(HTTPError); ok { 62 http.Error(w, httperr.Error(), httperr.Code) 63 return 64 } 65 66 http.Error(w, err.Error(), http.StatusBadRequest) 67 return 68 } 69 } 70 71 // HTTPFunc returns a http.HandleFunc which wraps the Handler for usage 72 // with a server. 73 func HTTPFunc(nx ContextHandler, befores ...func()) http.HandlerFunc { 74 return handlerImpl{ContextHandler: func(ctx *Ctx) error { 75 ctx.response.beforeFuncs = append(ctx.response.beforeFuncs, befores...) 76 return nx(ctx) 77 }}.ServeHTTP 78 } 79 80 // ServeHandler returns a http.Handler which serves request to the provided Handler. 81 func ServeHandler(h ContextHandler) http.Handler { 82 return handlerImpl{ContextHandler: h} 83 } 84 85 // GetFileMimeType returns associated mime type for giving file extension. 86 func GetFileMimeType(path string) string { 87 ext := filepath.Ext(path) 88 extVal := mime.TypeByExtension(ext) 89 if extVal == "" { 90 extVal = mediaTypes[ext] 91 } 92 return extVal 93 } 94 95 // JSONError writes the giving error message to the provided writer. 96 func JSONError(w http.ResponseWriter, statusCode int, errorCode string, message string, err error) error { 97 w.WriteHeader(statusCode) 98 99 var encoder = njson.JSONB() 100 encoder.ObjectFor("error", func(enc npkg.ObjectEncoder) { 101 enc.String("message", message) 102 enc.Int("status_code", statusCode) 103 enc.String("error_code", errorCode) 104 105 if encodableErr, ok := err.(npkg.EncodableObject); ok { 106 enc.Object("incident", encodableErr) 107 } 108 enc.String("incident", err.Error()) 109 }) 110 111 var _, werr = encoder.WriteTo(w) 112 return werr 113 } 114 115 // ParseAuthorization returns the scheme and token of the Authorization string 116 // if it's valid. 117 func ParseAuthorization(val string) (authType string, token string, err error) { 118 authSplit := strings.SplitN(val, " ", 2) 119 if len(authSplit) != 2 { 120 err = errors.New("invalid authorization: Expected content: `AuthType Token`") 121 return 122 } 123 124 authType = strings.TrimSpace(authSplit[0]) 125 token = strings.TrimSpace(authSplit[1]) 126 127 return 128 } 129 130 // ParseTokens parses the base64 encoded token sent as part of the Authorization string, 131 // It expects all parts of string to be seperated with ':', returning splitted slice. 132 func ParseTokens(val string) ([]string, error) { 133 decoded, err := base64.StdEncoding.DecodeString(val) 134 if err != nil { 135 return nil, err 136 } 137 138 return strings.Split(string(decoded), ":"), nil 139 }