25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

375 satır
11 KiB

  1. // Copyright 2017 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package promhttp
  14. import (
  15. "bufio"
  16. "io"
  17. "net"
  18. "net/http"
  19. )
  20. const (
  21. closeNotifier = 1 << iota
  22. flusher
  23. hijacker
  24. readerFrom
  25. pusher
  26. )
  27. type delegator interface {
  28. http.ResponseWriter
  29. Status() int
  30. Written() int64
  31. }
  32. type responseWriterDelegator struct {
  33. http.ResponseWriter
  34. status int
  35. written int64
  36. wroteHeader bool
  37. observeWriteHeader func(int)
  38. }
  39. func (r *responseWriterDelegator) Status() int {
  40. return r.status
  41. }
  42. func (r *responseWriterDelegator) Written() int64 {
  43. return r.written
  44. }
  45. func (r *responseWriterDelegator) WriteHeader(code int) {
  46. if r.observeWriteHeader != nil && !r.wroteHeader {
  47. // Only call observeWriteHeader for the 1st time. It's a bug if
  48. // WriteHeader is called more than once, but we want to protect
  49. // against it here. Note that we still delegate the WriteHeader
  50. // to the original ResponseWriter to not mask the bug from it.
  51. r.observeWriteHeader(code)
  52. }
  53. r.status = code
  54. r.wroteHeader = true
  55. r.ResponseWriter.WriteHeader(code)
  56. }
  57. func (r *responseWriterDelegator) Write(b []byte) (int, error) {
  58. // If applicable, call WriteHeader here so that observeWriteHeader is
  59. // handled appropriately.
  60. if !r.wroteHeader {
  61. r.WriteHeader(http.StatusOK)
  62. }
  63. n, err := r.ResponseWriter.Write(b)
  64. r.written += int64(n)
  65. return n, err
  66. }
  67. type (
  68. closeNotifierDelegator struct{ *responseWriterDelegator }
  69. flusherDelegator struct{ *responseWriterDelegator }
  70. hijackerDelegator struct{ *responseWriterDelegator }
  71. readerFromDelegator struct{ *responseWriterDelegator }
  72. pusherDelegator struct{ *responseWriterDelegator }
  73. )
  74. func (d closeNotifierDelegator) CloseNotify() <-chan bool {
  75. //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
  76. return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
  77. }
  78. func (d flusherDelegator) Flush() {
  79. // If applicable, call WriteHeader here so that observeWriteHeader is
  80. // handled appropriately.
  81. if !d.wroteHeader {
  82. d.WriteHeader(http.StatusOK)
  83. }
  84. d.ResponseWriter.(http.Flusher).Flush()
  85. }
  86. func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  87. return d.ResponseWriter.(http.Hijacker).Hijack()
  88. }
  89. func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
  90. // If applicable, call WriteHeader here so that observeWriteHeader is
  91. // handled appropriately.
  92. if !d.wroteHeader {
  93. d.WriteHeader(http.StatusOK)
  94. }
  95. n, err := d.ResponseWriter.(io.ReaderFrom).ReadFrom(re)
  96. d.written += n
  97. return n, err
  98. }
  99. func (d pusherDelegator) Push(target string, opts *http.PushOptions) error {
  100. return d.ResponseWriter.(http.Pusher).Push(target, opts)
  101. }
  102. var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32)
  103. func init() {
  104. // TODO(beorn7): Code generation would help here.
  105. pickDelegator[0] = func(d *responseWriterDelegator) delegator { // 0
  106. return d
  107. }
  108. pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1
  109. return closeNotifierDelegator{d}
  110. }
  111. pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2
  112. return flusherDelegator{d}
  113. }
  114. pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3
  115. return struct {
  116. *responseWriterDelegator
  117. http.Flusher
  118. http.CloseNotifier
  119. }{d, flusherDelegator{d}, closeNotifierDelegator{d}}
  120. }
  121. pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4
  122. return hijackerDelegator{d}
  123. }
  124. pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5
  125. return struct {
  126. *responseWriterDelegator
  127. http.Hijacker
  128. http.CloseNotifier
  129. }{d, hijackerDelegator{d}, closeNotifierDelegator{d}}
  130. }
  131. pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6
  132. return struct {
  133. *responseWriterDelegator
  134. http.Hijacker
  135. http.Flusher
  136. }{d, hijackerDelegator{d}, flusherDelegator{d}}
  137. }
  138. pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7
  139. return struct {
  140. *responseWriterDelegator
  141. http.Hijacker
  142. http.Flusher
  143. http.CloseNotifier
  144. }{d, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  145. }
  146. pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8
  147. return readerFromDelegator{d}
  148. }
  149. pickDelegator[readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 9
  150. return struct {
  151. *responseWriterDelegator
  152. io.ReaderFrom
  153. http.CloseNotifier
  154. }{d, readerFromDelegator{d}, closeNotifierDelegator{d}}
  155. }
  156. pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10
  157. return struct {
  158. *responseWriterDelegator
  159. io.ReaderFrom
  160. http.Flusher
  161. }{d, readerFromDelegator{d}, flusherDelegator{d}}
  162. }
  163. pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11
  164. return struct {
  165. *responseWriterDelegator
  166. io.ReaderFrom
  167. http.Flusher
  168. http.CloseNotifier
  169. }{d, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  170. }
  171. pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12
  172. return struct {
  173. *responseWriterDelegator
  174. io.ReaderFrom
  175. http.Hijacker
  176. }{d, readerFromDelegator{d}, hijackerDelegator{d}}
  177. }
  178. pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13
  179. return struct {
  180. *responseWriterDelegator
  181. io.ReaderFrom
  182. http.Hijacker
  183. http.CloseNotifier
  184. }{d, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
  185. }
  186. pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14
  187. return struct {
  188. *responseWriterDelegator
  189. io.ReaderFrom
  190. http.Hijacker
  191. http.Flusher
  192. }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
  193. }
  194. pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15
  195. return struct {
  196. *responseWriterDelegator
  197. io.ReaderFrom
  198. http.Hijacker
  199. http.Flusher
  200. http.CloseNotifier
  201. }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  202. }
  203. pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16
  204. return pusherDelegator{d}
  205. }
  206. pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17
  207. return struct {
  208. *responseWriterDelegator
  209. http.Pusher
  210. http.CloseNotifier
  211. }{d, pusherDelegator{d}, closeNotifierDelegator{d}}
  212. }
  213. pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18
  214. return struct {
  215. *responseWriterDelegator
  216. http.Pusher
  217. http.Flusher
  218. }{d, pusherDelegator{d}, flusherDelegator{d}}
  219. }
  220. pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19
  221. return struct {
  222. *responseWriterDelegator
  223. http.Pusher
  224. http.Flusher
  225. http.CloseNotifier
  226. }{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  227. }
  228. pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20
  229. return struct {
  230. *responseWriterDelegator
  231. http.Pusher
  232. http.Hijacker
  233. }{d, pusherDelegator{d}, hijackerDelegator{d}}
  234. }
  235. pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21
  236. return struct {
  237. *responseWriterDelegator
  238. http.Pusher
  239. http.Hijacker
  240. http.CloseNotifier
  241. }{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
  242. }
  243. pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22
  244. return struct {
  245. *responseWriterDelegator
  246. http.Pusher
  247. http.Hijacker
  248. http.Flusher
  249. }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
  250. }
  251. pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 23
  252. return struct {
  253. *responseWriterDelegator
  254. http.Pusher
  255. http.Hijacker
  256. http.Flusher
  257. http.CloseNotifier
  258. }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  259. }
  260. pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24
  261. return struct {
  262. *responseWriterDelegator
  263. http.Pusher
  264. io.ReaderFrom
  265. }{d, pusherDelegator{d}, readerFromDelegator{d}}
  266. }
  267. pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25
  268. return struct {
  269. *responseWriterDelegator
  270. http.Pusher
  271. io.ReaderFrom
  272. http.CloseNotifier
  273. }{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}}
  274. }
  275. pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26
  276. return struct {
  277. *responseWriterDelegator
  278. http.Pusher
  279. io.ReaderFrom
  280. http.Flusher
  281. }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}}
  282. }
  283. pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27
  284. return struct {
  285. *responseWriterDelegator
  286. http.Pusher
  287. io.ReaderFrom
  288. http.Flusher
  289. http.CloseNotifier
  290. }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  291. }
  292. pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28
  293. return struct {
  294. *responseWriterDelegator
  295. http.Pusher
  296. io.ReaderFrom
  297. http.Hijacker
  298. }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}}
  299. }
  300. pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29
  301. return struct {
  302. *responseWriterDelegator
  303. http.Pusher
  304. io.ReaderFrom
  305. http.Hijacker
  306. http.CloseNotifier
  307. }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
  308. }
  309. pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30
  310. return struct {
  311. *responseWriterDelegator
  312. http.Pusher
  313. io.ReaderFrom
  314. http.Hijacker
  315. http.Flusher
  316. }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
  317. }
  318. pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31
  319. return struct {
  320. *responseWriterDelegator
  321. http.Pusher
  322. io.ReaderFrom
  323. http.Hijacker
  324. http.Flusher
  325. http.CloseNotifier
  326. }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
  327. }
  328. }
  329. func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator {
  330. d := &responseWriterDelegator{
  331. ResponseWriter: w,
  332. observeWriteHeader: observeWriteHeaderFunc,
  333. }
  334. id := 0
  335. //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
  336. if _, ok := w.(http.CloseNotifier); ok {
  337. id += closeNotifier
  338. }
  339. if _, ok := w.(http.Flusher); ok {
  340. id += flusher
  341. }
  342. if _, ok := w.(http.Hijacker); ok {
  343. id += hijacker
  344. }
  345. if _, ok := w.(io.ReaderFrom); ok {
  346. id += readerFrom
  347. }
  348. if _, ok := w.(http.Pusher); ok {
  349. id += pusher
  350. }
  351. return pickDelegator[id](d)
  352. }