@@ -187,6 +187,87 @@ <h3 id="errors">Wrapping multiple errors</h3>
187
187
returns an error wrapping a list of errors.
188
188
</ p >
189
189
190
+ < h3 id ="http_responsecontroller "> HTTP ResponseController</ h3 >
191
+
192
+ < p >
193
+ The new
194
+ < a href ="/pkg/net/http/#ResponseController "> < code > "net/http".ResponseController</ code > </ a >
195
+ type provides access to extended per-request functionality not handled by the
196
+ < a href ="/pkg/net/http/#ResponseWriter "> < code > "net/http".ResponseWriter</ code > </ a > interface.
197
+ </ p >
198
+
199
+ < p >
200
+ Previously, we have added new per-request functionality by defining optional
201
+ interfaces which a < code > ResponseWriter</ code > can implement, such as
202
+ < a href ="/pkg/net/http/#Flusher "> < code > Flusher< code > </ a > . These interfaces
203
+ are not discoverable and clumsy to use.
204
+ </ p >
205
+
206
+ < p >
207
+ The < code > ResponseController</ code > type provides a clearer, more discoverable way
208
+ to add per-handler controls. Two such controls also added in Go 1.20 are
209
+ < code > SetReadDeadline</ code > and < code > SetWriteDeadline</ code > , which allow setting
210
+ per-request read and write deadlines. For example:
211
+ </ p >
212
+
213
+ < pre >
214
+ func RequestHandler(w ResponseWriter, r *Request) {
215
+ rc := http.NewResponseController(w)
216
+ rc.SetWriteDeadline(0) // disable Server.WriteTimeout when sending a large response
217
+ io.Copy(w, bigData)
218
+ }
219
+ </ pre >
220
+
221
+ < h3 id ="reverseproxy_rewrite "> New ReverseProxy Rewrite hook</ h3 >
222
+
223
+ < p >
224
+ The < a href ="/pkg/net/http/httputil/#ReverseProxy "> < code > httputil.ReverseProxy</ code > </ a >
225
+ forwarding proxy includes a new < code > Rewrite</ code > hook function, superseding the
226
+ previous < code > Director</ code > hook.
227
+ </ p >
228
+
229
+ < p >
230
+ The < code > Rewrite</ code > hook accepts a
231
+ < a href ="/pkg/net/http/httputil/#ProxyRequest "> < code > ProxyRequest</ code > </ a > parameter,
232
+ which includes both the inbound request received by the proxy and the outbound
233
+ request that it will send.
234
+ Unlike < code > Director</ code > hooks, which only operate on the outbound request,
235
+ this permits < code > Rewrite</ code > hooks to avoid certain scenarios where
236
+ a malicious inbound request may cause headers added by the hook
237
+ to be removed before forwarding.
238
+ See < a href ="https://go.dev/issue/50580 "> issue #50580</ a > .
239
+ </ p >
240
+
241
+ < p >
242
+ The < a href ="/pkg/net/http/httputil/#ProxyRequest.SetURL "> < code > ProxyRequest.SetURL</ code > </ a >
243
+ method routes the outbound request to a provided destination
244
+ and supersedes the < code > NewSingleHostReverseProxy</ code > function.
245
+ Unlike < code > NewSingleHostReverseProxy</ code > , < code > SetURL</ code >
246
+ also sets the < code > Host</ code > header of the outbound request.
247
+ </ p >
248
+
249
+ < p >
250
+ The
251
+ < a href ="/pkg/net/http/httputil/#ProxyRequest.SetXForwarded "> < code > ProxyRequest.SetXForwarded</ code > </ a >
252
+ method sets the < code > X-Forwarded-For</ code > , < code > X-Forwarded-Host</ code > ,
253
+ and < code > X-Forwarded-Proto</ code > headers of the outbound request.
254
+ When using a < code > Rewrite</ code > , these headers are not added by default.
255
+ </ p >
256
+
257
+ < p >
258
+ An example of a < code > Rewrite</ code > hook using these features is:
259
+ </ p >
260
+
261
+ < pre >
262
+ proxyHandler := &httputil.ReverseProxy{
263
+ Rewrite: func(r *httputil.ProxyRequest) {
264
+ r.SetURL(outboundURL) // Forward request to outboundURL.
265
+ r.SetXForwarded() // Set X-Forwarded-* headers.
266
+ r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
267
+ },
268
+ }
269
+ </ pre >
270
+
190
271
< h3 id ="minor_library_changes "> Minor changes to the library</ h3 >
191
272
192
273
< p >
@@ -476,56 +557,70 @@ <h3 id="minor_library_changes">Minor changes to the library</h3>
476
557
477
558
< dl id ="net/http "> < dt > < a href ="/pkg/net/http/ "> net/http</ a > </ dt >
478
559
< dd >
479
- < p > <!-- https://go.dev/issue/41773 -->
480
- TODO: < a href ="https://go.dev/issue/41773 "> https://go.dev/issue/41773</ a > : add Server.OptionsHandler to allow custom handling of OPTIONS *
481
- </ p >
560
+ < p > <!-- https://go.dev/issue/541360 -->
561
+ The new < code > ResponseController</ code > type provides access to extended per-request
562
+ functionality not handled by the < code > ResponseWriter< code > interface.
563
+ < p >
482
564
483
- < p > <!-- CL 356410 -->
484
- TODO: < a href ="https://go.dev/cl/356410 "> https://go.dev/cl/356410</ a > : net/http: add Server.DisableOptionsHandler for custom handling of OPTIONS *; modified api/next/41773.txt
565
+ < p >
566
+ The new < code > ResponseController.SetReadDeadline</ code > and
567
+ < code > ResponseController.SetWriteDeadline</ code > methods permit setting
568
+ per-request read and write deadlines.
485
569
</ p >
486
570
487
571
< p > <!-- https://go.dev/issue/51914 -->
488
- TODO: < a href ="https://go.dev/issue/51914 "> https://go.dev/issue/51914</ a > : support for the 103 status code
572
+ The < code > ResponseWriter.WriteHeader</ code > function now supports sending
573
+ < code > 1xx</ code > status codes.
489
574
</ p >
490
575
491
- < p > <!-- https://go.dev/issue/53896 -->
492
- TODO: < a href ="https://go.dev/issue/53896 "> https://go.dev/issue/53896</ a > : easier access to HTTP/2 error codes
576
+ < p > <!-- https://go.dev/issue/41773 -->
577
+ The new < code > Server.DisableGeneralOptionsHandler</ code > configuration setting
578
+ allows disabling the default < code > OPTIONS *</ code > handler.
493
579
</ p >
494
580
495
581
< p > <!-- https://go.dev/issue/54299 -->
496
- TODO: < a href ="https://go.dev/issue/54299 "> https://go.dev/issue/54299</ a > : add Transport.OnProxyConnectResponse
582
+ The new < code > Transport.OnProxyConnectResponse</ code > hook is called
583
+ when a < code > Transport</ code > receives an HTTP response from a proxy
584
+ for a < code > CONNECT</ code > request.
497
585
</ p >
498
586
499
- < p > <!-- CL 418614 -->
500
- TODO: < a href ="https://go.dev/cl/418614 "> https://go.dev/cl/418614</ a > : net/http: accept HEAD requests with a body; accept HEAD requests with a body
587
+ < p > <!-- https://go.dev/issue/53960 -->
588
+ The HTTP server now accepts HEAD requests containing a body,
589
+ rather than rejecting them as invalid.
501
590
</ p >
502
591
503
- < p > <!-- CL 436890 -->
504
- TODO: < a href ="https://go.dev/cl/436890 "> https://go.dev/cl/436890</ a > : net/http: add ResponseController and per-handler timeouts; modified api/next/54136.txt
592
+ < p > <!-- https://go.dev/issue/53896 -->
593
+ HTTP/2 stream errors returned by < code > net/http</ code > functions may be converted
594
+ to a < code > "golang.org/x/net/http2".StreamError</ code > using < code > errors.As</ code > .
505
595
</ p >
506
596
507
- < p > <!-- CL 447216 -->
508
- TODO: < a href ="https://go.dev/cl/447216 "> https://go.dev/cl/447216</ a > : net/http: add Transport.OnProxyConnectResponse; modified api/next/54299.txt
597
+ < p > <!-- https://go.dev/cl/397734 -->
598
+ Leading and trailing spaces are trimmed from cookie names,
599
+ rather than being rejected as invalid.
600
+ For example, a cookie setting of "name =value"
601
+ is now accepted as setting the cookie "name".
509
602
</ p >
510
603
</ dd >
511
604
</ dl > <!-- net/http -->
512
605
513
606
< dl id ="net/http/httputil "> < dt > < a href ="/pkg/net/http/httputil/ "> net/http/httputil</ a > </ dt >
514
607
< dd >
515
- < p > <!-- https://go.dev/issue/50465 -->
516
- TODO: < a href ="https://go.dev/issue/50465 "> https://go.dev/issue/50465</ a > : add X-Forwarded-Proto and X-Forwarded-Host by default
517
- </ p >
518
-
519
608
< p > <!-- https://go.dev/issue/53002 -->
520
- TODO: < a href =" https://go.dev/issue/53002 " > https://go.dev/issue/53002 </ a > : replace Director with Rewrite
609
+ The new < code > ReverseProxy </ code > hook supersedes the existing < code > Rewrite</ code > hook.
521
610
</ p >
522
611
523
- < p > <!-- CL 407214 -->
524
- TODO: < a href ="https://go.dev/cl/407214 "> https://go.dev/cl/407214</ a > : net/http/httputil: add ReverseProxy.Rewrite; modified api/next/53002.txt
612
+ < p > <!-- https://go.dev/issue/50465 -->
613
+ < code > ReverseProxy</ code > now adds
614
+ < code > X-Forwarded-Proto</ code > and < code > X-Forwarded-Host</ code > headers
615
+ to forwarded requests.
616
+ These headers are added to all requests forwarded by a < code > Director</ code > hook,
617
+ and to requests forwarded by a < code > Rewrite</ code > hook which calls the
618
+ < code > ProxyRequest.SetXForwarded</ code > function.
525
619
</ p >
526
620
527
- < p > <!-- CL 407414 -->
528
- TODO: < a href ="https://go.dev/cl/407414 "> https://go.dev/cl/407414</ a > : net/http/httputil: add X-Forwarded-{Host,Proto} headers in ReverseProxy
621
+ < p > <!-- CL 407375 -->
622
+ < code > ReverseProxy</ code > no longer adds a < code > User-Agent</ code > header
623
+ to forwarded requests when the incoming request does not have one.
529
624
</ p >
530
625
</ dd >
531
626
</ dl > <!-- net/http/httputil -->
0 commit comments