negociate.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package helper
  2. // Copyright 2013 The Go Authors. All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style
  5. // license that can be found in the LICENSE file or at
  6. // https://developers.google.com/open-source/licenses/bsd.
  7. import (
  8. "net/http"
  9. "strings"
  10. "github.com/ncarlier/webhookd/pkg/helper/header"
  11. )
  12. // NegotiateContentType returns the best offered content type for the request's
  13. // Accept header. If two offers match with equal weight, then the more specific
  14. // offer is preferred. For example, text/* trumps */*. If two offers match
  15. // with equal weight and specificity, then the offer earlier in the list is
  16. // preferred. If no offers match, then defaultOffer is returned.
  17. func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
  18. bestOffer := defaultOffer
  19. bestQ := -1.0
  20. bestWild := 3
  21. specs := header.ParseAccept(r.Header, "Accept")
  22. for _, offer := range offers {
  23. for _, spec := range specs {
  24. switch {
  25. case spec.Q == 0.0:
  26. // ignore
  27. case spec.Q < bestQ:
  28. // better match found
  29. case spec.Value == "*/*":
  30. if spec.Q > bestQ || bestWild > 2 {
  31. bestQ = spec.Q
  32. bestWild = 2
  33. bestOffer = offer
  34. }
  35. case strings.HasSuffix(spec.Value, "/*"):
  36. if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
  37. (spec.Q > bestQ || bestWild > 1) {
  38. bestQ = spec.Q
  39. bestWild = 1
  40. bestOffer = offer
  41. }
  42. case strings.HasSuffix(offer, "/*"):
  43. if strings.HasPrefix(spec.Value, offer[:len(offer)-1]) &&
  44. (spec.Q > bestQ || bestWild > 1) {
  45. bestQ = spec.Q
  46. bestWild = 1
  47. bestOffer = spec.Value
  48. }
  49. default:
  50. if spec.Value == offer &&
  51. (spec.Q > bestQ || bestWild > 0) {
  52. bestQ = spec.Q
  53. bestWild = 0
  54. bestOffer = offer
  55. }
  56. }
  57. }
  58. }
  59. return bestOffer
  60. }