@@ -3,79 +3,338 @@ package http
3
3
import (
4
4
"net/http"
5
5
"net/http/httptest"
6
+ "net/url"
6
7
"testing"
7
8
8
9
cors "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors"
9
10
10
- "github.com/ipfs/go-ipfs/commands"
11
+ cmds "github.com/ipfs/go-ipfs/commands"
12
+ ipfscmd "github.com/ipfs/go-ipfs/core/commands"
13
+ coremock "github.com/ipfs/go-ipfs/core/mock"
11
14
)
12
15
13
16
func assertHeaders (t * testing.T , resHeaders http.Header , reqHeaders map [string ]string ) {
14
17
for name , value := range reqHeaders {
15
18
if resHeaders .Get (name ) != value {
16
- t .Errorf ("Invalid header ` %s', wanted ` %s', got ` %s'" , name , value , resHeaders .Get (name ))
19
+ t .Errorf ("Invalid header ' %s', wanted ' %s', got ' %s'" , name , value , resHeaders .Get (name ))
17
20
}
18
21
}
19
22
}
20
23
21
- func originCfg (origin string ) * ServerConfig {
24
+ func assertStatus (t * testing.T , actual , expected int ) {
25
+ if actual != expected {
26
+ t .Errorf ("Expected status: %d got: %d" , expected , actual )
27
+ }
28
+ }
29
+
30
+ func originCfg (origins []string ) * ServerConfig {
22
31
return & ServerConfig {
23
32
CORSOpts : & cors.Options {
24
- AllowedOrigins : []string {origin },
33
+ AllowedOrigins : origins ,
34
+ },
35
+ }
36
+ }
37
+
38
+ type testCase struct {
39
+ Method string
40
+ Path string
41
+ Code int
42
+ Origin string
43
+ Referer string
44
+ AllowOrigins []string
45
+ ReqHeaders map [string ]string
46
+ ResHeaders map [string ]string
47
+ }
48
+
49
+ func getTestServer (t * testing.T , origins []string ) * httptest.Server {
50
+ cmdsCtx , err := coremock .MockCmdsCtx ()
51
+ if err != nil {
52
+ t .Error ("failure to initialize mock cmds ctx" , err )
53
+ return nil
54
+ }
55
+
56
+ cmdRoot := & cmds.Command {
57
+ Subcommands : map [string ]* cmds.Command {
58
+ "version" : ipfscmd .VersionCmd ,
25
59
},
26
60
}
61
+
62
+ handler := NewHandler (cmdsCtx , cmdRoot , originCfg (origins ))
63
+ return httptest .NewServer (handler )
27
64
}
28
65
29
- func TestDisallowedOrigin (t * testing.T ) {
30
- res := httptest .NewRecorder ()
31
- req , _ := http .NewRequest ("GET" , "http://example.com/foo" , nil )
32
- req .Header .Add ("Origin" , "http://barbaz.com" )
33
-
34
- handler := NewHandler (commands.Context {}, nil , originCfg ("" ))
35
- handler .ServeHTTP (res , req )
36
-
37
- assertHeaders (t , res .Header (), map [string ]string {
38
- "Access-Control-Allow-Origin" : "" ,
39
- "Access-Control-Allow-Methods" : "" ,
40
- "Access-Control-Allow-Credentials" : "" ,
41
- "Access-Control-Max-Age" : "" ,
42
- "Access-Control-Expose-Headers" : "" ,
43
- })
66
+ func (tc * testCase ) test (t * testing.T ) {
67
+ // defaults
68
+ method := tc .Method
69
+ if method == "" {
70
+ method = "GET"
71
+ }
72
+
73
+ path := tc .Path
74
+ if path == "" {
75
+ path = "/api/v0/version"
76
+ }
77
+
78
+ expectCode := tc .Code
79
+ if expectCode == 0 {
80
+ expectCode = 200
81
+ }
82
+
83
+ // request
84
+ req , err := http .NewRequest (method , path , nil )
85
+ if err != nil {
86
+ t .Error (err )
87
+ return
88
+ }
89
+
90
+ for k , v := range tc .ReqHeaders {
91
+ req .Header .Add (k , v )
92
+ }
93
+ if tc .Origin != "" {
94
+ req .Header .Add ("Origin" , tc .Origin )
95
+ }
96
+ if tc .Referer != "" {
97
+ req .Header .Add ("Referer" , tc .Referer )
98
+ }
99
+
100
+ // server
101
+ server := getTestServer (t , tc .AllowOrigins )
102
+ if server == nil {
103
+ return
104
+ }
105
+ defer server .Close ()
106
+
107
+ req .URL , err = url .Parse (server .URL + path )
108
+ if err != nil {
109
+ t .Error (err )
110
+ return
111
+ }
112
+
113
+ res , err := http .DefaultClient .Do (req )
114
+ if err != nil {
115
+ t .Error (err )
116
+ return
117
+ }
118
+
119
+ // checks
120
+ t .Log ("GET" , server .URL + path , req .Header , res .Header )
121
+ assertHeaders (t , res .Header , tc .ResHeaders )
122
+ assertStatus (t , res .StatusCode , expectCode )
123
+ }
124
+
125
+ func TestDisallowedOrigins (t * testing.T ) {
126
+ gtc := func (origin string , allowedOrigins []string ) testCase {
127
+ return testCase {
128
+ Origin : origin ,
129
+ AllowOrigins : allowedOrigins ,
130
+ ResHeaders : map [string ]string {
131
+ ACAOrigin : "" ,
132
+ ACAMethods : "" ,
133
+ ACACredentials : "" ,
134
+ "Access-Control-Max-Age" : "" ,
135
+ "Access-Control-Expose-Headers" : "" ,
136
+ },
137
+ Code : http .StatusForbidden ,
138
+ }
139
+ }
140
+
141
+ tcs := []testCase {
142
+ gtc ("http://barbaz.com" , nil ),
143
+ gtc ("http://barbaz.com" , []string {"http://localhost" }),
144
+ gtc ("http://127.0.0.1" , []string {"http://localhost" }),
145
+ gtc ("http://localhost" , []string {"http://127.0.0.1" }),
146
+ gtc ("http://127.0.0.1:1234" , nil ),
147
+ gtc ("http://localhost:1234" , nil ),
148
+ }
149
+
150
+ for _ , tc := range tcs {
151
+ tc .test (t )
152
+ }
153
+ }
154
+
155
+ func TestAllowedOrigins (t * testing.T ) {
156
+ gtc := func (origin string , allowedOrigins []string ) testCase {
157
+ return testCase {
158
+ Origin : origin ,
159
+ AllowOrigins : allowedOrigins ,
160
+ ResHeaders : map [string ]string {
161
+ ACAOrigin : origin ,
162
+ ACAMethods : "" ,
163
+ ACACredentials : "" ,
164
+ "Access-Control-Max-Age" : "" ,
165
+ "Access-Control-Expose-Headers" : "" ,
166
+ },
167
+ Code : http .StatusOK ,
168
+ }
169
+ }
170
+
171
+ tcs := []testCase {
172
+ gtc ("http://barbaz.com" , []string {"http://barbaz.com" , "http://localhost" }),
173
+ gtc ("http://localhost" , []string {"http://barbaz.com" , "http://localhost" }),
174
+ gtc ("http://localhost" , nil ),
175
+ gtc ("http://127.0.0.1" , nil ),
176
+ }
177
+
178
+ for _ , tc := range tcs {
179
+ tc .test (t )
180
+ }
44
181
}
45
182
46
183
func TestWildcardOrigin (t * testing.T ) {
47
- res := httptest .NewRecorder ()
48
- req , _ := http .NewRequest ("GET" , "http://example.com/foo" , nil )
49
- req .Header .Add ("Origin" , "http://foobar.com" )
50
-
51
- handler := NewHandler (commands.Context {}, nil , originCfg ("*" ))
52
- handler .ServeHTTP (res , req )
53
-
54
- assertHeaders (t , res .Header (), map [string ]string {
55
- "Access-Control-Allow-Origin" : "http://foobar.com" ,
56
- "Access-Control-Allow-Methods" : "" ,
57
- "Access-Control-Allow-Headers" : "" ,
58
- "Access-Control-Allow-Credentials" : "" ,
59
- "Access-Control-Max-Age" : "" ,
60
- "Access-Control-Expose-Headers" : "" ,
61
- })
184
+ gtc := func (origin string , allowedOrigins []string ) testCase {
185
+ return testCase {
186
+ Origin : origin ,
187
+ AllowOrigins : allowedOrigins ,
188
+ ResHeaders : map [string ]string {
189
+ ACAOrigin : origin ,
190
+ ACAMethods : "" ,
191
+ ACACredentials : "" ,
192
+ "Access-Control-Max-Age" : "" ,
193
+ "Access-Control-Expose-Headers" : "" ,
194
+ },
195
+ Code : http .StatusOK ,
196
+ }
197
+ }
198
+
199
+ tcs := []testCase {
200
+ gtc ("http://barbaz.com" , []string {"*" }),
201
+ gtc ("http://barbaz.com" , []string {"http://localhost" , "*" }),
202
+ gtc ("http://127.0.0.1" , []string {"http://localhost" , "*" }),
203
+ gtc ("http://localhost" , []string {"http://127.0.0.1" , "*" }),
204
+ gtc ("http://127.0.0.1" , []string {"*" }),
205
+ gtc ("http://localhost" , []string {"*" }),
206
+ gtc ("http://127.0.0.1:1234" , []string {"*" }),
207
+ gtc ("http://localhost:1234" , []string {"*" }),
208
+ }
209
+
210
+ for _ , tc := range tcs {
211
+ tc .test (t )
212
+ }
213
+ }
214
+
215
+ func TestDisallowedReferer (t * testing.T ) {
216
+ gtc := func (referer string , allowedOrigins []string ) testCase {
217
+ return testCase {
218
+ Origin : "http://localhost" ,
219
+ Referer : referer ,
220
+ AllowOrigins : allowedOrigins ,
221
+ ResHeaders : map [string ]string {
222
+ ACAOrigin : "http://localhost" ,
223
+ ACAMethods : "" ,
224
+ ACACredentials : "" ,
225
+ "Access-Control-Max-Age" : "" ,
226
+ "Access-Control-Expose-Headers" : "" ,
227
+ },
228
+ Code : http .StatusForbidden ,
229
+ }
230
+ }
231
+
232
+ tcs := []testCase {
233
+ gtc ("http://foobar.com" , nil ),
234
+ gtc ("http://localhost:1234" , nil ),
235
+ gtc ("http://127.0.0.1:1234" , nil ),
236
+ }
237
+
238
+ for _ , tc := range tcs {
239
+ tc .test (t )
240
+ }
241
+ }
242
+
243
+ func TestAllowedReferer (t * testing.T ) {
244
+ gtc := func (referer string , allowedOrigins []string ) testCase {
245
+ return testCase {
246
+ Origin : "http://localhost" ,
247
+ AllowOrigins : allowedOrigins ,
248
+ ResHeaders : map [string ]string {
249
+ ACAOrigin : "http://localhost" ,
250
+ ACAMethods : "" ,
251
+ ACACredentials : "" ,
252
+ "Access-Control-Max-Age" : "" ,
253
+ "Access-Control-Expose-Headers" : "" ,
254
+ },
255
+ Code : http .StatusOK ,
256
+ }
257
+ }
258
+
259
+ tcs := []testCase {
260
+ gtc ("http://barbaz.com" , []string {"http://barbaz.com" , "http://localhost" }),
261
+ gtc ("http://localhost" , []string {"http://barbaz.com" , "http://localhost" }),
262
+ gtc ("http://localhost" , nil ),
263
+ gtc ("http://127.0.0.1" , nil ),
264
+ }
265
+
266
+ for _ , tc := range tcs {
267
+ tc .test (t )
268
+ }
269
+ }
270
+
271
+ func TestWildcardReferer (t * testing.T ) {
272
+ gtc := func (origin string , allowedOrigins []string ) testCase {
273
+ return testCase {
274
+ Origin : origin ,
275
+ AllowOrigins : allowedOrigins ,
276
+ ResHeaders : map [string ]string {
277
+ ACAOrigin : origin ,
278
+ ACAMethods : "" ,
279
+ ACACredentials : "" ,
280
+ "Access-Control-Max-Age" : "" ,
281
+ "Access-Control-Expose-Headers" : "" ,
282
+ },
283
+ Code : http .StatusOK ,
284
+ }
285
+ }
286
+
287
+ tcs := []testCase {
288
+ gtc ("http://barbaz.com" , []string {"*" }),
289
+ gtc ("http://barbaz.com" , []string {"http://localhost" , "*" }),
290
+ gtc ("http://127.0.0.1" , []string {"http://localhost" , "*" }),
291
+ gtc ("http://localhost" , []string {"http://127.0.0.1" , "*" }),
292
+ gtc ("http://127.0.0.1" , []string {"*" }),
293
+ gtc ("http://localhost" , []string {"*" }),
294
+ gtc ("http://127.0.0.1:1234" , []string {"*" }),
295
+ gtc ("http://localhost:1234" , []string {"*" }),
296
+ }
297
+
298
+ for _ , tc := range tcs {
299
+ tc .test (t )
300
+ }
62
301
}
63
302
64
303
func TestAllowedMethod (t * testing.T ) {
65
- res := httptest .NewRecorder ()
66
- req , _ := http .NewRequest ("OPTIONS" , "http://example.com/foo" , nil )
67
- req .Header .Add ("Origin" , "http://www.foobar.com" )
68
- req .Header .Add ("Access-Control-Request-Method" , "PUT" )
69
-
70
- handler := NewHandler (commands.Context {}, nil , originCfg ("http://www.foobar.com" ))
71
- handler .ServeHTTP (res , req )
72
-
73
- assertHeaders (t , res .Header (), map [string ]string {
74
- "Access-Control-Allow-Origin" : "http://www.foobar.com" ,
75
- "Access-Control-Allow-Methods" : "PUT" ,
76
- "Access-Control-Allow-Headers" : "" ,
77
- "Access-Control-Allow-Credentials" : "" ,
78
- "Access-Control-Max-Age" : "" ,
79
- "Access-Control-Expose-Headers" : "" ,
80
- })
304
+ gtc := func (method string , ok bool ) testCase {
305
+ code := http .StatusOK
306
+ hdrs := map [string ]string {
307
+ ACAOrigin : "http://localhost" ,
308
+ ACAMethods : method ,
309
+ ACACredentials : "" ,
310
+ "Access-Control-Max-Age" : "" ,
311
+ "Access-Control-Expose-Headers" : "" ,
312
+ }
313
+
314
+ if ! ok {
315
+ hdrs [ACAOrigin ] = ""
316
+ hdrs [ACAMethods ] = ""
317
+ }
318
+
319
+ return testCase {
320
+ Method : "OPTIONS" ,
321
+ Origin : "http://localhost" ,
322
+ AllowOrigins : []string {"*" },
323
+ ReqHeaders : map [string ]string {
324
+ "Access-Control-Request-Method" : method ,
325
+ },
326
+ ResHeaders : hdrs ,
327
+ Code : code ,
328
+ }
329
+ }
330
+
331
+ tcs := []testCase {
332
+ gtc ("PUT" , true ),
333
+ gtc ("GET" , true ),
334
+ gtc ("FOOBAR" , false ),
335
+ }
336
+
337
+ for _ , tc := range tcs {
338
+ tc .test (t )
339
+ }
81
340
}
0 commit comments