You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
4.3 KiB
201 lines
4.3 KiB
package http |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"encoding/xml" |
|
"git.diulo.com/mogfee/kit/middleware" |
|
"git.diulo.com/mogfee/kit/transport" |
|
"git.diulo.com/mogfee/kit/transport/http/binding" |
|
"github.com/gorilla/mux" |
|
"io" |
|
"net/http" |
|
"net/url" |
|
"time" |
|
) |
|
|
|
type Context interface { |
|
context.Context |
|
Vars() url.Values |
|
Query() url.Values |
|
Form() url.Values |
|
Header() http.Header |
|
Request() *http.Request |
|
Response() http.ResponseWriter |
|
Middleware(middleware.Handler) middleware.Handler |
|
Bind(interface{}) error |
|
BindVars(interface{}) error |
|
BindQuery(interface{}) error |
|
BindForm(interface{}) error |
|
Returns(interface{}, error) error |
|
Result(int, interface{}) error |
|
JSON(int, interface{}) error |
|
XML(int, interface{}) error |
|
String(int, string) error |
|
Blob(int, string, []byte) error |
|
Stream(int, string, io.Reader) error |
|
Reset(http.ResponseWriter, *http.Request) |
|
} |
|
type responseWriter struct { |
|
code int |
|
w http.ResponseWriter |
|
} |
|
|
|
func (r *responseWriter) Header() http.Header { |
|
return r.w.Header() |
|
} |
|
|
|
func (r *responseWriter) Write(bytes []byte) (int, error) { |
|
r.w.WriteHeader(r.code) |
|
return r.w.Write(bytes) |
|
} |
|
|
|
func (r *responseWriter) WriteHeader(statusCode int) { |
|
r.code = statusCode |
|
} |
|
|
|
func (r *responseWriter) reset(res http.ResponseWriter) { |
|
r.w = res |
|
r.code = http.StatusOK |
|
} |
|
|
|
type wrapper struct { |
|
router *Router |
|
req *http.Request |
|
res http.ResponseWriter |
|
w responseWriter |
|
} |
|
|
|
func (w *wrapper) Deadline() (deadline time.Time, ok bool) { |
|
if w.req == nil { |
|
return time.Time{}, false |
|
} |
|
return w.req.Context().Deadline() |
|
} |
|
|
|
func (w *wrapper) Done() <-chan struct{} { |
|
if w.req == nil { |
|
return nil |
|
} |
|
return w.req.Context().Done() |
|
} |
|
|
|
func (w *wrapper) Err() error { |
|
if w.req == nil { |
|
return context.Canceled |
|
} |
|
return w.req.Context().Err() |
|
} |
|
|
|
func (w *wrapper) Value(key any) any { |
|
if w.req == nil { |
|
return nil |
|
} |
|
return w.req.Context().Value(key) |
|
} |
|
|
|
func (w *wrapper) Vars() url.Values { |
|
raws := mux.Vars(w.req) |
|
vars := make(url.Values, len(raws)) |
|
for k, v := range raws { |
|
vars[k] = []string{v} |
|
} |
|
return vars |
|
} |
|
|
|
func (w *wrapper) Query() url.Values { |
|
return w.req.URL.Query() |
|
} |
|
|
|
func (w *wrapper) Form() url.Values { |
|
if err := w.req.ParseForm(); err != nil { |
|
return url.Values{} |
|
} |
|
return w.req.Form |
|
} |
|
|
|
func (w *wrapper) Header() http.Header { |
|
return w.req.Header |
|
} |
|
|
|
func (w *wrapper) Request() *http.Request { |
|
return w.req |
|
} |
|
|
|
func (w *wrapper) Response() http.ResponseWriter { |
|
return w.res |
|
} |
|
|
|
func (w *wrapper) Middleware(handler middleware.Handler) middleware.Handler { |
|
if tr, ok := transport.FromServerContext(w.req.Context()); ok { |
|
return middleware.Chain(w.router.srv.middleware.Match(tr.Operation())...)(handler) |
|
} |
|
return middleware.Chain(w.router.srv.middleware.Match(w.req.URL.Path)...)(handler) |
|
} |
|
|
|
func (w *wrapper) Bind(i any) error { |
|
return w.router.srv.decBody(w.req, i) |
|
} |
|
|
|
func (w *wrapper) BindVars(i interface{}) error { |
|
return w.router.srv.decVars(w.req, i) |
|
} |
|
|
|
func (w *wrapper) BindQuery(i interface{}) error { |
|
return w.router.srv.decQuery(w.req, i) |
|
} |
|
|
|
func (w *wrapper) BindForm(i interface{}) error { |
|
return binding.BindForm(w.req, i) |
|
} |
|
|
|
func (w *wrapper) Returns(i interface{}, err error) error { |
|
if err != nil { |
|
return err |
|
} |
|
return w.router.srv.enc(&w.w, w.req, i) |
|
} |
|
|
|
func (w *wrapper) Result(i int, i2 interface{}) error { |
|
w.w.WriteHeader(i) |
|
return w.router.srv.enc(&w.w, w.req, i2) |
|
} |
|
|
|
func (w *wrapper) JSON(i int, i2 interface{}) error { |
|
w.res.Header().Set("Content-Type", "application/json") |
|
w.res.WriteHeader(i) |
|
return json.NewEncoder(w.res).Encode(i2) |
|
} |
|
|
|
func (w *wrapper) XML(i int, i2 interface{}) error { |
|
w.res.Header().Set("Content-Type", "application/xml") |
|
w.res.WriteHeader(i) |
|
return xml.NewEncoder(w.res).Encode(i2) |
|
} |
|
|
|
func (w *wrapper) String(i int, s string) error { |
|
w.res.Header().Set("Content-Type", "text/plain") |
|
w.res.WriteHeader(i) |
|
_, err := w.res.Write([]byte(s)) |
|
return err |
|
} |
|
|
|
func (w *wrapper) Blob(i int, s string, bytes []byte) error { |
|
w.res.Header().Set("Content-Type", s) |
|
w.res.WriteHeader(i) |
|
_, err := w.res.Write(bytes) |
|
return err |
|
} |
|
|
|
func (w *wrapper) Stream(i int, s string, reader io.Reader) error { |
|
w.res.Header().Set("Content-Type", s) |
|
w.res.WriteHeader(i) |
|
_, err := io.Copy(w.res, reader) |
|
return err |
|
} |
|
|
|
func (w *wrapper) Reset(writer http.ResponseWriter, request *http.Request) { |
|
w.w.reset(writer) |
|
w.res = writer |
|
w.req = request |
|
}
|
|
|