Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

197 řádky
4.4 KiB

  1. // Copyright 2015 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package proxyutil
  15. import (
  16. "fmt"
  17. "net/http"
  18. "strconv"
  19. )
  20. // Header is a generic representation of a set of HTTP headers for requests and
  21. // responses.
  22. type Header struct {
  23. h http.Header
  24. host func() string
  25. cl func() int64
  26. te func() []string
  27. setHost func(string)
  28. setCL func(int64)
  29. setTE func([]string)
  30. }
  31. // RequestHeader returns a new set of headers from a request.
  32. func RequestHeader(req *http.Request) *Header {
  33. return &Header{
  34. h: req.Header,
  35. host: func() string { return req.Host },
  36. cl: func() int64 { return req.ContentLength },
  37. te: func() []string { return req.TransferEncoding },
  38. setHost: func(host string) { req.Host = host },
  39. setCL: func(cl int64) { req.ContentLength = cl },
  40. setTE: func(te []string) { req.TransferEncoding = te },
  41. }
  42. }
  43. // ResponseHeader returns a new set of headers from a request.
  44. func ResponseHeader(res *http.Response) *Header {
  45. return &Header{
  46. h: res.Header,
  47. host: func() string { return "" },
  48. cl: func() int64 { return res.ContentLength },
  49. te: func() []string { return res.TransferEncoding },
  50. setHost: func(string) {},
  51. setCL: func(cl int64) { res.ContentLength = cl },
  52. setTE: func(te []string) { res.TransferEncoding = te },
  53. }
  54. }
  55. // Set sets value at header name for the request or response.
  56. func (h *Header) Set(name, value string) error {
  57. switch http.CanonicalHeaderKey(name) {
  58. case "Host":
  59. h.setHost(value)
  60. case "Content-Length":
  61. cl, err := strconv.ParseInt(value, 10, 64)
  62. if err != nil {
  63. return err
  64. }
  65. h.setCL(cl)
  66. case "Transfer-Encoding":
  67. h.setTE([]string{value})
  68. default:
  69. h.h.Set(name, value)
  70. }
  71. return nil
  72. }
  73. // Add appends the value to the existing header at name for the request or
  74. // response.
  75. func (h *Header) Add(name, value string) error {
  76. switch http.CanonicalHeaderKey(name) {
  77. case "Host":
  78. if h.host() != "" {
  79. return fmt.Errorf("proxyutil: illegal header multiple: %s", "Host")
  80. }
  81. return h.Set(name, value)
  82. case "Content-Length":
  83. if h.cl() > 0 {
  84. return fmt.Errorf("proxyutil: illegal header multiple: %s", "Content-Length")
  85. }
  86. return h.Set(name, value)
  87. case "Transfer-Encoding":
  88. h.setTE(append(h.te(), value))
  89. default:
  90. h.h.Add(name, value)
  91. }
  92. return nil
  93. }
  94. // Get returns the first value at header name for the request or response.
  95. func (h *Header) Get(name string) string {
  96. switch http.CanonicalHeaderKey(name) {
  97. case "Host":
  98. return h.host()
  99. case "Content-Length":
  100. if h.cl() < 0 {
  101. return ""
  102. }
  103. return strconv.FormatInt(h.cl(), 10)
  104. case "Transfer-Encoding":
  105. if len(h.te()) < 1 {
  106. return ""
  107. }
  108. return h.te()[0]
  109. default:
  110. return h.h.Get(name)
  111. }
  112. }
  113. // All returns all the values for header name. If the header does not exist it
  114. // returns nil, false.
  115. func (h *Header) All(name string) ([]string, bool) {
  116. switch http.CanonicalHeaderKey(name) {
  117. case "Host":
  118. if h.host() == "" {
  119. return nil, false
  120. }
  121. return []string{h.host()}, true
  122. case "Content-Length":
  123. if h.cl() <= 0 {
  124. return nil, false
  125. }
  126. return []string{strconv.FormatInt(h.cl(), 10)}, true
  127. case "Transfer-Encoding":
  128. if h.te() == nil {
  129. return nil, false
  130. }
  131. return h.te(), true
  132. default:
  133. vs, ok := h.h[http.CanonicalHeaderKey(name)]
  134. return vs, ok
  135. }
  136. }
  137. // Del deletes the header at name for the request or response.
  138. func (h *Header) Del(name string) {
  139. switch http.CanonicalHeaderKey(name) {
  140. case "Host":
  141. h.setHost("")
  142. case "Content-Length":
  143. h.setCL(-1)
  144. case "Transfer-Encoding":
  145. h.setTE(nil)
  146. default:
  147. h.h.Del(name)
  148. }
  149. }
  150. // Map returns an http.Header that includes Host, Content-Length, and
  151. // Transfer-Encoding.
  152. func (h *Header) Map() http.Header {
  153. hm := make(http.Header)
  154. for k, vs := range h.h {
  155. hm[k] = vs
  156. }
  157. for _, k := range []string{
  158. "Host",
  159. "Content-Length",
  160. "Transfer-Encoding",
  161. } {
  162. vs, ok := h.All(k)
  163. if !ok {
  164. continue
  165. }
  166. hm[k] = vs
  167. }
  168. return hm
  169. }