Source file
src/net/http/cgi/integration_test.go
1
2
3
4
5
6
7
8
9 package cgi
10
11 import (
12 "bytes"
13 "errors"
14 "fmt"
15 "internal/testenv"
16 "io"
17 "net/http"
18 "net/http/httptest"
19 "net/url"
20 "os"
21 "strings"
22 "testing"
23 )
24
25
26
27 func TestHostingOurselves(t *testing.T) {
28 testenv.MustHaveExec(t)
29
30 h := &Handler{
31 Path: os.Args[0],
32 Root: "/test.go",
33 }
34 expectedMap := map[string]string{
35 "test": "Hello CGI-in-CGI",
36 "param-a": "b",
37 "param-foo": "bar",
38 "env-GATEWAY_INTERFACE": "CGI/1.1",
39 "env-HTTP_HOST": "example.com",
40 "env-PATH_INFO": "",
41 "env-QUERY_STRING": "foo=bar&a=b",
42 "env-REMOTE_ADDR": "1.2.3.4",
43 "env-REMOTE_HOST": "1.2.3.4",
44 "env-REMOTE_PORT": "1234",
45 "env-REQUEST_METHOD": "GET",
46 "env-REQUEST_URI": "/test.go?foo=bar&a=b",
47 "env-SCRIPT_FILENAME": os.Args[0],
48 "env-SCRIPT_NAME": "/test.go",
49 "env-SERVER_NAME": "example.com",
50 "env-SERVER_PORT": "80",
51 "env-SERVER_SOFTWARE": "go",
52 }
53 replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
54
55 if expected, got := "text/plain; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
56 t.Errorf("got a Content-Type of %q; expected %q", got, expected)
57 }
58 if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
59 t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
60 }
61 }
62
63 type customWriterRecorder struct {
64 w io.Writer
65 *httptest.ResponseRecorder
66 }
67
68 func (r *customWriterRecorder) Write(p []byte) (n int, err error) {
69 return r.w.Write(p)
70 }
71
72 type limitWriter struct {
73 w io.Writer
74 n int
75 }
76
77 func (w *limitWriter) Write(p []byte) (n int, err error) {
78 if len(p) > w.n {
79 p = p[:w.n]
80 }
81 if len(p) > 0 {
82 n, err = w.w.Write(p)
83 w.n -= n
84 }
85 if w.n == 0 {
86 err = errors.New("past write limit")
87 }
88 return
89 }
90
91
92
93 func TestKillChildAfterCopyError(t *testing.T) {
94 testenv.MustHaveExec(t)
95
96 h := &Handler{
97 Path: os.Args[0],
98 Root: "/test.go",
99 }
100 req, _ := http.NewRequest("GET", "http://example.com/test.go?write-forever=1", nil)
101 rec := httptest.NewRecorder()
102 var out bytes.Buffer
103 const writeLen = 50 << 10
104 rw := &customWriterRecorder{&limitWriter{&out, writeLen}, rec}
105
106 h.ServeHTTP(rw, req)
107 if out.Len() != writeLen || out.Bytes()[0] != 'a' {
108 t.Errorf("unexpected output: %q", out.Bytes())
109 }
110 }
111
112
113
114 func TestChildOnlyHeaders(t *testing.T) {
115 testenv.MustHaveExec(t)
116
117 h := &Handler{
118 Path: os.Args[0],
119 Root: "/test.go",
120 }
121 expectedMap := map[string]string{
122 "_body": "",
123 }
124 replay := runCgiTest(t, h, "GET /test.go?no-body=1 HTTP/1.0\nHost: example.com\n\n", expectedMap)
125 if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
126 t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
127 }
128 }
129
130
131
132 func TestNilRequestBody(t *testing.T) {
133 testenv.MustHaveExec(t)
134
135 h := &Handler{
136 Path: os.Args[0],
137 Root: "/test.go",
138 }
139 expectedMap := map[string]string{
140 "nil-request-body": "false",
141 }
142 _ = runCgiTest(t, h, "POST /test.go?nil-request-body=1 HTTP/1.0\nHost: example.com\n\n", expectedMap)
143 _ = runCgiTest(t, h, "POST /test.go?nil-request-body=1 HTTP/1.0\nHost: example.com\nContent-Length: 0\n\n", expectedMap)
144 }
145
146 func TestChildContentType(t *testing.T) {
147 testenv.MustHaveExec(t)
148
149 h := &Handler{
150 Path: os.Args[0],
151 Root: "/test.go",
152 }
153 var tests = []struct {
154 name string
155 body string
156 wantCT string
157 }{
158 {
159 name: "no body",
160 wantCT: "text/plain; charset=utf-8",
161 },
162 {
163 name: "html",
164 body: "<html><head><title>test page</title></head><body>This is a body</body></html>",
165 wantCT: "text/html; charset=utf-8",
166 },
167 {
168 name: "text",
169 body: strings.Repeat("gopher", 86),
170 wantCT: "text/plain; charset=utf-8",
171 },
172 {
173 name: "jpg",
174 body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024),
175 wantCT: "image/jpeg",
176 },
177 }
178 for _, tt := range tests {
179 t.Run(tt.name, func(t *testing.T) {
180 expectedMap := map[string]string{"_body": tt.body}
181 req := fmt.Sprintf("GET /test.go?exact-body=%s HTTP/1.0\nHost: example.com\n\n", url.QueryEscape(tt.body))
182 replay := runCgiTest(t, h, req, expectedMap)
183 if got := replay.Header().Get("Content-Type"); got != tt.wantCT {
184 t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT)
185 }
186 })
187 }
188 }
189
190
191 func Test500WithNoHeaders(t *testing.T) { want500Test(t, "/immediate-disconnect") }
192 func Test500WithNoContentType(t *testing.T) { want500Test(t, "/no-content-type") }
193 func Test500WithEmptyHeaders(t *testing.T) { want500Test(t, "/empty-headers") }
194
195 func want500Test(t *testing.T, path string) {
196 h := &Handler{
197 Path: os.Args[0],
198 Root: "/test.go",
199 }
200 expectedMap := map[string]string{
201 "_body": "",
202 }
203 replay := runCgiTest(t, h, "GET "+path+" HTTP/1.0\nHost: example.com\n\n", expectedMap)
204 if replay.Code != 500 {
205 t.Errorf("Got code %d; want 500", replay.Code)
206 }
207 }
208
View as plain text