handle.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package http
  2. import (
  3. "net/http"
  4. "strings"
  5. "github.com/go-kratos/kratos/v2/encoding"
  6. "github.com/go-kratos/kratos/v2/errors"
  7. "github.com/go-kratos/kratos/v2/encoding/json"
  8. _ "github.com/go-kratos/kratos/v2/encoding/proto"
  9. )
  10. // decodeRequest decodes the request body to object.
  11. //func DecodeRequest(req *http.Request, v interface{}) error {
  12. // method := strings.ToUpper(req.Method)
  13. // if method == "POST" || method == "PUT" || method == "DELETE" {
  14. // if _, ok := v.(*emptypb.Empty); ok {
  15. // return binding.BindForm(req, v)
  16. // }
  17. // subtype := contentSubtype(req.Header.Get(ContentTypeHeader))
  18. // if codec := encoding.GetCodec(subtype); codec != nil {
  19. // data, err := ioutil.ReadAll(req.Body)
  20. // if err != nil {
  21. // return err
  22. // }
  23. // return codec.Unmarshal(data, v)
  24. // }
  25. // }
  26. // return binding.BindForm(req, v)
  27. //}
  28. func ErrHandle(w http.ResponseWriter, r *http.Request, err error) {
  29. se, ok := errors.FromError(err)
  30. if !ok {
  31. se = &errors.StatusError{
  32. Code: 10500,
  33. Message: err.Error(),
  34. }
  35. }
  36. if se.Code == -1 {
  37. return
  38. }
  39. codec := codecForRequest(r)
  40. w.Header().Set(ContentTypeHeader, contentType(codec.Name()))
  41. if se.Code == 0 {
  42. w.WriteHeader(200)
  43. } else if se.Code >= 302 && se.Code <= 303 {
  44. w.WriteHeader(int(se.Code))
  45. http.Redirect(w, r, se.Message, int(se.Code))
  46. return
  47. } else {
  48. if se.Code < 10000 {
  49. se.Code = 10000 + se.Code
  50. }
  51. if se.Code < 10100 && se.Message == "" {
  52. se.Message = "系统错误"
  53. }
  54. w.WriteHeader(400)
  55. }
  56. data, _ := codec.Marshal(se)
  57. _, _ = w.Write(data)
  58. }
  59. const baseContentType = "application"
  60. var (
  61. acceptHeader = http.CanonicalHeaderKey("Accept")
  62. ContentTypeHeader = http.CanonicalHeaderKey("Content-Type")
  63. )
  64. func contentType(subtype string) string {
  65. return strings.Join([]string{baseContentType, subtype}, "/")
  66. }
  67. // codecForRequest get encoding.Codec via http.Request
  68. func codecForRequest(r *http.Request) encoding.Codec {
  69. var codec encoding.Codec
  70. for _, accept := range r.Header[acceptHeader] {
  71. codeName := contentSubtype(accept)
  72. if codeName == "json" {
  73. codec = encoding.GetCodec(json.Name)
  74. break
  75. }
  76. if codec = encoding.GetCodec(codeName); codec != nil {
  77. break
  78. }
  79. }
  80. if codec == nil {
  81. codec = encoding.GetCodec(json.Name)
  82. }
  83. return codec
  84. }
  85. func contentSubtype(contentType string) string {
  86. if contentType == baseContentType {
  87. return ""
  88. }
  89. if !strings.HasPrefix(contentType, baseContentType) {
  90. return ""
  91. }
  92. switch contentType[len(baseContentType)] {
  93. case '/', ';':
  94. if i := strings.Index(contentType, ";"); i != -1 {
  95. return contentType[len(baseContentType)+1 : i]
  96. }
  97. return contentType[len(baseContentType)+1:]
  98. default:
  99. return ""
  100. }
  101. }