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

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
}