package http import ( "context" "encoding/json" "encoding/xml" "io/ioutil" "net/http" "net/url" "strings" "git.chuangxin1.com/csacred/toolkit" ) // DecodeRequestFunc extracts a user-domain request object from an HTTP // request object. It's designed to be used in HTTP servers, for server-side // endpoints. One straightforward DecodeRequestFunc could be something that // JSON decodes from the request body to the concrete response type. type DecodeRequestFunc func(context.Context, *http.Request) (request interface{}, err error) func header(w http.ResponseWriter, contentType string) { w.Header().Set(`Content-Type`, contentType) w.Header().Set(`X-Power`, toolkit.LibName+`/`+toolkit.LibVersion) w.WriteHeader(http.StatusOK) } // WriteJSON response JSON data. func WriteJSON(w http.ResponseWriter, response interface{}) error { header(w, `application/json; charset=utf-8`) return json.NewEncoder(w).Encode(response) } // WriteXML response XML data. func WriteXML(w http.ResponseWriter, response interface{}) error { header(w, `application/xml; charset=utf-8`) return xml.NewEncoder(w).Encode(response) } // WriteBytes response bytes func WriteBytes(w http.ResponseWriter, response interface{}) error { header(w, `text/html; charset=utf-8`) w.Write(response.([]byte)) return nil } // WriteCtxJSON response JSON data. func WriteCtxJSON(ctx context.Context, w http.ResponseWriter, response interface{}) error { return WriteJSON(w, response) } // WriteCtxXML response XML data. func WriteCtxXML(ctx context.Context, w http.ResponseWriter, response interface{}) error { return WriteXML(w, response) } // WriteCtxBytes response text data. func WriteCtxBytes(ctx context.Context, w http.ResponseWriter, response interface{}) error { return WriteBytes(w, response) } // EncodeError request encode error response func EncodeError(_ context.Context, err error, w http.ResponseWriter) { WriteJSON(w, toolkit.ErrReplyData(toolkit.ErrParamsError, err.Error())) } // EncodeXMLError request encode error response func EncodeXMLError(_ context.Context, err error, w http.ResponseWriter) { WriteXML(w, toolkit.ErrReplyData(toolkit.ErrParamsError, err.Error())) } // DecodeJSONResponse decode client func DecodeJSONResponse(ctx context.Context, r *http.Response) (interface{}, error) { var res toolkit.ReplyData if err := json.NewDecoder(r.Body).Decode(&res); err != nil { return toolkit.ErrReplyData(toolkit.ErrException, `data format error`), err } return res, nil } // DecodeXMLResponse decode client func DecodeXMLResponse(ctx context.Context, r *http.Response) (interface{}, error) { var res toolkit.ReplyData if err := xml.NewDecoder(r.Body).Decode(&res); err != nil { return toolkit.ErrReplyData(toolkit.ErrException, `data format error`), err } return res, nil } // DecodeBytesResponse decode client func DecodeBytesResponse(ctx context.Context, r *http.Response) (interface{}, error) { return ioutil.ReadAll(r.Body) } // PopulateRequestContext is a RequestFunc that populates several values into // the context from the HTTP request. Those values may be extracted using the // corresponding ContextKey type in this package. func PopulateRequestContext(ctx context.Context, r *http.Request) context.Context { var accessToken string accessToken = r.URL.Query().Get(toolkit.VarUserAuthorization) if accessToken == "" { if cookie, err := r.Cookie(toolkit.VarUserAuthorization); err == nil { accessToken, _ = url.QueryUnescape(cookie.Value) } } token := r.Header.Get(toolkit.HTTPHeaderAuthorization) if accessToken == "" { if len(token) > 6 && strings.ToUpper(token[0:7]) == "BEARER " { accessToken = token[7:] } } for k, v := range map[toolkit.ContextKey]string{ toolkit.ContextKeyRequestMethod: r.Method, toolkit.ContextKeyRequestURI: r.RequestURI, toolkit.ContextKeyRequestPath: r.URL.Path, toolkit.ContextKeyRequestProto: r.Proto, toolkit.ContextKeyRequestHost: r.Host, toolkit.ContextKeyRequestRemoteAddr: r.RemoteAddr, toolkit.ContextKeyRequestXForwardedFor: r.Header.Get("X-Forwarded-For"), toolkit.ContextKeyRequestXForwardedProto: r.Header.Get("X-Forwarded-Proto"), toolkit.ContextKeyRequestAuthorization: token, toolkit.ContextKeyRequestReferer: r.Header.Get("Referer"), toolkit.ContextKeyRequestUserAgent: r.Header.Get("User-Agent"), toolkit.ContextKeyRequestXRequestID: r.Header.Get("X-Request-Id"), toolkit.ContextKeyRequestAccept: r.Header.Get("Accept"), toolkit.ContextKeyAccessToken: accessToken, } { //fmt.Println(k, v) ctx = context.WithValue(ctx, k, v) } return ctx }