Sorry to resurrect a month old thread, but I just implemented bullet #2 
with this patch.

I need to disable the automatic 100-continue behavior so that my handler 
can reply with a 40X status before the client read the 100-contine and 
starts sending data.



On Saturday, September 17, 2016 at 12:08:29 AM UTC-4, David Anderson wrote:
>
> Tricky one. A couple of options spring to mind, none of them amazingly 
> good:
>
>    - Use a GCE Network LB instead of HTTP LB. You can bring the TCP 
>    sessions straight to your web servers, with load-balancing done 
>    per-TCP-session rather than per-HTTP-request.
>    - Build your web server using a modified Go stdlib codebase that 
>    removes this conditional block: 
>    https://golang.org/src/net/http/server.go#L1562 . If you do this, I 
>    suggest also filing a bug against Go to evaluate whether "don't do 
>    automatic Continue support" should be added as a Server knob.
>    - Stick the Go web servers behind a non-Go proxy layer (e.g. nginx) 
>    that strips out the "Expect: 100-continue" header before forwarding to the 
>    Go server. Run one nginx per Go server, on the same machines (or in the 
>    same Kubernetes pods if using GKE), so that the system properties look the 
>    same from the POV of the upstream load-balancer (same number of backends, 
>    same arrangement...).
>    - Wait for GCE to support 100-Continue. Given that 100-Continue is 
>    almost non-existent on the web, personally I wouldn't hold my breath, I 
>    suspect it's a low-priority item.
>    - You say your clients can't be modified... Can't they? I've never 
>    heard of browsers using 100-Continue unprompted, so if it is just 
>    chrome/firefox/IE, what are you doing that's causing them to use 
>    100-Continue? Or are they some other client software like Mercurial?
>
> - Dave
>
> On Fri, Sep 16, 2016 at 10:00 AM, Ian Rose <ianr...@gmail.com 
> <javascript:>> wrote:
>
>> Howdy,
>>
>> I'm currently running a group of Go web servers behind an HTTP(s) load 
>> balancer on Google Compute Engine.  Unfortunately I have learned that GCE 
>> load balancers do not support the "Expect: 100-continue" header [1].  From 
>> my experiments, it appears that it isn't actually the request header that 
>> causes the problem, but instead is the server's "100 Continue" response 
>> that the load balancer dies on.  Specifically, the load balancer responds 
>> with a 502 to the client.
>>
>> Any suggestions on how to deal with this?  We don't control our clients 
>> (they are just "browsers across the internet") so solving things on that 
>> side isn't possible.  After digging through the net/http code a bit, my 
>> best thought is to hijack the connection, which (I think) will prevent a 
>> "100 Continue" status from being sent.  I'm concerned, however, that this 
>> won't work in all cases - for example http2 connections are not hijackable (
>> https://github.com/golang/go/issues/15312).
>>
>> Is there a better path forward?
>>
>> Thanks,
>> Ian
>>
>> [1] https://code.google.com/p/google-compute-engine/issues/detail?id=298 
>>   (also see "notes and restrictions" here: 
>> https://cloud.google.com/compute/docs/load-balancing/http/)
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 51a66c3..6c01228 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1679,14 +1679,16 @@ func (c *conn) serve(ctx context.Context) {
 
 		// Expect 100 Continue support
 		req := w.req
-		if req.expectsContinue() {
-			if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
-				// Wrap the Body reader with one that replies on the connection
-				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+		if !c.server.NoAuto100Continue {
+			if req.expectsContinue() {
+				if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
+					// Wrap the Body reader with one that replies on the connection
+					req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+				}
+			} else if req.Header.get("Expect") != "" {
+				w.sendExpectationFailed()
+				return
 			}
-		} else if req.Header.get("Expect") != "" {
-			w.sendExpectationFailed()
-			return
 		}
 
 		c.curReq.Store(w)
@@ -2246,6 +2248,11 @@ type Server struct {
 	// standard logger.
 	ErrorLog *log.Logger
 
+	// NoAuto100Continue disabled the default behavior of the
+	// server to automatically reply with a 100-continue response
+	// before invoking a handler.
+	NoAuto100Continue bool
+
 	disableKeepAlives int32     // accessed atomically.
 	nextProtoOnce     sync.Once // guards setupHTTP2_* init
 	nextProtoErr      error     // result of http2.ConfigureServer if used

Reply via email to