You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

80 lines
2.2 KiB

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