Skip to content

Commit 1bdfe3f

Browse files
authored
re-apply PR #235 to v2 (#290)
This change slipped through the cracks because it was added to v1 after v2 was forked, but before v2 was landed.
1 parent b08cb36 commit 1bdfe3f

File tree

4 files changed

+59
-46
lines changed

4 files changed

+59
-46
lines changed

v2/appengine.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ func Main() {
5454
internal.Main()
5555
}
5656

57+
// Middleware wraps an http handler so that it can make GAE API calls
58+
var Middleware func(http.Handler) http.Handler = internal.Middleware
59+
5760
// IsDevAppServer reports whether the App Engine app is running in the
5861
// development App Server.
5962
func IsDevAppServer() bool {

v2/internal/api.go

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -84,53 +84,63 @@ func apiURL(ctx netcontext.Context) *url.URL {
8484
}
8585
}
8686

87-
func handleHTTP(w http.ResponseWriter, r *http.Request) {
88-
c := &context{
89-
req: r,
90-
outHeader: w.Header(),
91-
}
92-
r = r.WithContext(withContext(r.Context(), c))
93-
c.req = r
94-
95-
// Patch up RemoteAddr so it looks reasonable.
96-
if addr := r.Header.Get(userIPHeader); addr != "" {
97-
r.RemoteAddr = addr
98-
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
99-
r.RemoteAddr = addr
100-
} else {
101-
// Should not normally reach here, but pick a sensible default anyway.
102-
r.RemoteAddr = "127.0.0.1"
103-
}
104-
// The address in the headers will most likely be of these forms:
105-
// 123.123.123.123
106-
// 2001:db8::1
107-
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
108-
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
109-
// Assume the remote address is only a host; add a default port.
110-
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
111-
}
112-
113-
executeRequestSafely(c, r)
114-
c.outHeader = nil // make sure header changes aren't respected any more
115-
116-
// Avoid nil Write call if c.Write is never called.
117-
if c.outCode != 0 {
118-
w.WriteHeader(c.outCode)
119-
}
120-
if c.outBody != nil {
121-
w.Write(c.outBody)
122-
}
87+
// Middleware wraps an http handler so that it can make GAE API calls
88+
func Middleware(next http.Handler) http.Handler {
89+
return handleHTTPMiddleware(executeRequestSafelyMiddleware(next))
12390
}
12491

125-
func executeRequestSafely(c *context, r *http.Request) {
126-
defer func() {
127-
if x := recover(); x != nil {
128-
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
129-
c.outCode = 500
92+
func handleHTTPMiddleware(next http.Handler) http.Handler {
93+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
94+
c := &context{
95+
req: r,
96+
outHeader: w.Header(),
97+
}
98+
r = r.WithContext(withContext(r.Context(), c))
99+
c.req = r
100+
101+
// Patch up RemoteAddr so it looks reasonable.
102+
if addr := r.Header.Get(userIPHeader); addr != "" {
103+
r.RemoteAddr = addr
104+
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
105+
r.RemoteAddr = addr
106+
} else {
107+
// Should not normally reach here, but pick a sensible default anyway.
108+
r.RemoteAddr = "127.0.0.1"
109+
}
110+
// The address in the headers will most likely be of these forms:
111+
// 123.123.123.123
112+
// 2001:db8::1
113+
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
114+
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
115+
// Assume the remote address is only a host; add a default port.
116+
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
130117
}
131-
}()
132118

133-
http.DefaultServeMux.ServeHTTP(c, r)
119+
next.ServeHTTP(c, r)
120+
c.outHeader = nil // make sure header changes aren't respected any more
121+
122+
// Avoid nil Write call if c.Write is never called.
123+
if c.outCode != 0 {
124+
w.WriteHeader(c.outCode)
125+
}
126+
if c.outBody != nil {
127+
w.Write(c.outBody)
128+
}
129+
})
130+
}
131+
132+
func executeRequestSafelyMiddleware(next http.Handler) http.Handler {
133+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
134+
defer func() {
135+
if x := recover(); x != nil {
136+
c := w.(*context)
137+
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
138+
c.outCode = 500
139+
}
140+
}()
141+
142+
next.ServeHTTP(w, r)
143+
})
134144
}
135145

136146
func renderPanic(x interface{}) string {

v2/internal/api_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func TestRemoteAddr(t *testing.T) {
292292
Header: tc.headers,
293293
Body: ioutil.NopCloser(bytes.NewReader(nil)),
294294
}
295-
handleHTTP(httptest.NewRecorder(), r)
295+
Middleware(http.DefaultServeMux).ServeHTTP(httptest.NewRecorder(), r)
296296
if addr != tc.addr {
297297
t.Errorf("Header %v, got %q, want %q", tc.headers, addr, tc.addr)
298298
}
@@ -309,7 +309,7 @@ func TestPanickingHandler(t *testing.T) {
309309
Body: ioutil.NopCloser(bytes.NewReader(nil)),
310310
}
311311
rec := httptest.NewRecorder()
312-
handleHTTP(rec, r)
312+
Middleware(http.DefaultServeMux).ServeHTTP(rec, r)
313313
if rec.Code != 500 {
314314
t.Errorf("Panicking handler returned HTTP %d, want HTTP %d", rec.Code, 500)
315315
}

v2/internal/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func Main() {
3030
if IsDevAppServer() {
3131
host = "127.0.0.1"
3232
}
33-
if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
33+
if err := http.ListenAndServe(host+":"+port, Middleware(http.DefaultServeMux)); err != nil {
3434
log.Fatalf("http.ListenAndServe: %v", err)
3535
}
3636
}

0 commit comments

Comments
 (0)