123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package http
- import (
- "encoding/json"
- "fmt"
- "google.golang.org/genproto/googleapis/rpc/errdetails"
- "google.golang.org/grpc/status"
- "io"
- "net/http"
- "strings"
- )
- type Response struct {
- Code int `json:"code"`
- Reason string `json:"reason"`
- Message string `json:"message"`
- Metadata interface{} `json:"metadata"`
- w http.ResponseWriter
- ct string
- }
- func NewResponse(w http.ResponseWriter) *Response {
- return &Response{
- w: w,
- }
- }
- func (r *Response) StatusCode(code int) *Response {
- r.Code = code
- return r
- }
- func (r *Response) ContentType(ct string) *Response {
- r.ct = ct
- return r
- }
- func (r *Response) getCode(defaultCode int) int {
- if r.Code != 0 {
- return r.Code
- }
- return defaultCode
- }
- func (r *Response) getContentType(defaultContentType string) string {
- if r.ct != "" {
- return r.ct
- }
- return defaultContentType
- }
- func (r *Response) Error(err error) {
- r.buildResponseBody(err)
- r.w.Header().Set("Content-Type", r.getContentType("application/json"))
- r.w.WriteHeader(r.getCode(http.StatusInternalServerError))
- body, err := json.Marshal(r)
- if err != nil {
- r.w.Write([]byte(err.Error()))
- return
- }
- r.w.Write(body)
- }
- func (r *Response) Json(body []byte) {
- r.w.Header().Set("Content-Type", r.getContentType("application/json"))
- r.w.WriteHeader(r.getCode(http.StatusOK))
- r.w.Write(body)
- }
- func (r *Response) Raw(rc io.Reader) {
- r.w.Header().Set("Content-Type", r.getContentType("application/octet-stream"))
- r.w.WriteHeader(r.getCode(http.StatusOK))
- io.Copy(r.w, rc)
- }
- func (r *Response) Redirect(url string) {
- r.w.Header().Set("Location", url)
- r.w.WriteHeader(r.getCode(http.StatusOK))
- r.w.Write([]byte(""))
- }
- func (r *Response) JsonOk(ok bool) {
- j, _ := json.Marshal(map[string]bool{
- "ok": ok,
- })
- r.Json(j)
- }
- func (r *Response) Abort() {
- r.ContentType("text/plain").Raw(strings.NewReader(http.StatusText(r.getCode(http.StatusInternalServerError))))
- }
- func (r *Response) Download(body io.Reader, filename string) {
- r.w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
- r.Raw(body)
- }
- func (r *Response) buildResponseBody(err error) {
- s := status.Convert(err)
- pb := s.Proto()
- st := httpStatusFromGrpcCode(s.Code())
- if len(s.Details()) > 0 {
- for _, detail := range s.Details() {
- switch d := detail.(type) {
- case *errdetails.ErrorInfo:
- r.Reason = d.Reason
- r.Metadata = d.Metadata
- break
- }
- }
- } else {
- r.Reason = "UNKNOWN_ERROR"
- }
- r.Message = pb.GetMessage()
- r.Code = st
- }
|