handle.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package http
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strings"
  6. "github.com/go-kratos/kratos/v2/errors"
  7. "github.com/go-kratos/kratos/v2/encoding/json"
  8. "google.golang.org/grpc/encoding"
  9. // init encoding
  10. _ "google.golang.org/grpc/encoding/gzip"
  11. _ "google.golang.org/grpc/encoding/proto"
  12. )
  13. func ErrHandle(w http.ResponseWriter, r *http.Request, err error) {
  14. se, ok := errors.FromError(err)
  15. if !ok {
  16. se = &errors.StatusError{
  17. Code: 2,
  18. Message: err.Error(),
  19. }
  20. }
  21. codec := codecForRequest(r)
  22. data, _ := codec.Marshal(se)
  23. w.Header().Set(ContentTypeHeader, contentType(codec.Name()))
  24. w.WriteHeader(200)
  25. _, _ = w.Write(data)
  26. }
  27. const baseContentType = "application"
  28. var (
  29. acceptHeader = http.CanonicalHeaderKey("Accept")
  30. ContentTypeHeader = http.CanonicalHeaderKey("Content-Type")
  31. )
  32. func contentType(subtype string) string {
  33. return strings.Join([]string{baseContentType, subtype}, "/")
  34. }
  35. // codecForRequest get encoding.Codec via http.Request
  36. func codecForRequest(r *http.Request) encoding.Codec {
  37. var codec encoding.Codec
  38. for _, accept := range r.Header[acceptHeader] {
  39. if codec = encoding.GetCodec(contentSubtype(accept)); codec != nil {
  40. break
  41. }
  42. }
  43. if codec == nil {
  44. codec = encoding.GetCodec(json.Name)
  45. fmt.Println(codec == nil)
  46. }
  47. fmt.Println(codec == nil)
  48. return codec
  49. }
  50. func contentSubtype(contentType string) string {
  51. if contentType == baseContentType {
  52. return ""
  53. }
  54. if !strings.HasPrefix(contentType, baseContentType) {
  55. return ""
  56. }
  57. switch contentType[len(baseContentType)] {
  58. case '/', ';':
  59. if i := strings.Index(contentType, ";"); i != -1 {
  60. return contentType[len(baseContentType)+1 : i]
  61. }
  62. return contentType[len(baseContentType)+1:]
  63. default:
  64. return ""
  65. }
  66. }