| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library shelf.request_test; | 5 library shelf.request_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 import 'package:shelf/shelf.dart'; | 10 import 'package:shelf/shelf.dart'; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 test('protocolVersion defaults to "1.1"', () { | 22 test('protocolVersion defaults to "1.1"', () { |
| 23 var request = new Request('GET', LOCALHOST_URI); | 23 var request = new Request('GET', LOCALHOST_URI); |
| 24 expect(request.protocolVersion, '1.1'); | 24 expect(request.protocolVersion, '1.1'); |
| 25 }); | 25 }); |
| 26 | 26 |
| 27 test('provide non-default protocolVersion', () { | 27 test('provide non-default protocolVersion', () { |
| 28 var request = new Request('GET', LOCALHOST_URI, protocolVersion: '1.0'); | 28 var request = new Request('GET', LOCALHOST_URI, protocolVersion: '1.0'); |
| 29 expect(request.protocolVersion, '1.0'); | 29 expect(request.protocolVersion, '1.0'); |
| 30 }); | 30 }); |
| 31 | 31 |
| 32 test('requestedUri must be absolute', () { | 32 group("url", () { |
| 33 expect(() => new Request('GET', Uri.parse('/path')), throwsArgumentError); | 33 test("defaults to the requestedUri's relativized path and query", () { |
| 34 var request = |
| 35 new Request('GET', Uri.parse("http://localhost/foo/bar?q=1")); |
| 36 expect(request.url, equals(Uri.parse("foo/bar?q=1"))); |
| 37 }); |
| 38 |
| 39 test("is inferred from handlerPath if possible", () { |
| 40 var request = new Request( |
| 41 'GET', Uri.parse("http://localhost/foo/bar?q=1"), |
| 42 handlerPath: '/foo/'); |
| 43 expect(request.url, equals(Uri.parse("bar?q=1"))); |
| 44 }); |
| 45 |
| 46 test("uses the given value if passed", () { |
| 47 var request = new Request( |
| 48 'GET', Uri.parse("http://localhost/foo/bar?q=1"), |
| 49 url: Uri.parse("bar?q=1")); |
| 50 expect(request.url, equals(Uri.parse("bar?q=1"))); |
| 51 }); |
| 34 }); | 52 }); |
| 35 | 53 |
| 36 test('if uri is null, scriptName must be null', () { | 54 group("handlerPath", () { |
| 37 expect(() => new Request('GET', Uri.parse('/path'), | 55 test("defaults to '/'", () { |
| 38 scriptName: '/script/name'), throwsArgumentError); | 56 var request = new Request('GET', Uri.parse("http://localhost/foo/bar")); |
| 57 expect(request.handlerPath, equals('/')); |
| 58 }); |
| 59 |
| 60 test("is inferred from url if possible", () { |
| 61 var request = new Request( |
| 62 'GET', Uri.parse("http://localhost/foo/bar?q=1"), |
| 63 url: Uri.parse("bar?q=1")); |
| 64 expect(request.handlerPath, equals("/foo/")); |
| 65 }); |
| 66 |
| 67 test("uses the given value if passed", () { |
| 68 var request = new Request( |
| 69 'GET', Uri.parse("http://localhost/foo/bar?q=1"), |
| 70 handlerPath: '/foo/'); |
| 71 expect(request.handlerPath, equals("/foo/")); |
| 72 }); |
| 73 |
| 74 test("adds a trailing slash to the given value if necessary", () { |
| 75 var request = new Request( |
| 76 'GET', Uri.parse("http://localhost/foo/bar?q=1"), |
| 77 handlerPath: '/foo'); |
| 78 expect(request.handlerPath, equals("/foo/")); |
| 79 expect(request.url, equals(Uri.parse("bar?q=1"))); |
| 80 }); |
| 39 }); | 81 }); |
| 40 | 82 |
| 41 test('if scriptName is null, uri must be null', () { | 83 group("errors", () { |
| 42 var relativeUri = new Uri(path: '/cool/beans.html'); | 84 group('requestedUri', () { |
| 43 expect(() => new Request('GET', Uri.parse('/path'), url: relativeUri), | 85 test('must be absolute', () { |
| 44 throwsArgumentError); | 86 expect(() => new Request('GET', Uri.parse('/path')), |
| 45 }); | 87 throwsArgumentError); |
| 88 }); |
| 46 | 89 |
| 47 test('uri must be relative', () { | 90 test('may not have a fragment', () { |
| 48 var relativeUri = Uri.parse('http://localhost/test'); | 91 expect(() { |
| 92 new Request('GET', Uri.parse('http://localhost/#fragment')); |
| 93 }, throwsArgumentError); |
| 94 }); |
| 95 }); |
| 49 | 96 |
| 50 expect(() => new Request('GET', LOCALHOST_URI, | 97 group('url', () { |
| 51 url: relativeUri, scriptName: '/news'), throwsArgumentError); | 98 test('must be relative', () { |
| 99 expect(() { |
| 100 new Request('GET', Uri.parse('http://localhost/test'), |
| 101 url: Uri.parse('http://localhost/test')); |
| 102 }, throwsArgumentError); |
| 103 }); |
| 52 | 104 |
| 53 // NOTE: explicitly testing fragments due to Issue 18053 | 105 test('may not be root-relative', () { |
| 54 relativeUri = Uri.parse('http://localhost/test#fragment'); | 106 expect(() { |
| 107 new Request('GET', Uri.parse('http://localhost/test'), |
| 108 url: Uri.parse('/test')); |
| 109 }, throwsArgumentError); |
| 110 }); |
| 55 | 111 |
| 56 expect(() => new Request('GET', LOCALHOST_URI, | 112 test('may not have a fragment', () { |
| 57 url: relativeUri, scriptName: '/news'), throwsArgumentError); | 113 expect(() { |
| 58 }); | 114 new Request('GET', Uri.parse('http://localhost/test'), |
| 115 url: Uri.parse('test#fragment')); |
| 116 }, throwsArgumentError); |
| 117 }); |
| 59 | 118 |
| 60 test('uri and scriptName', () { | 119 test('must be a suffix of requestedUri', () { |
| 61 var pathInfo = '/pages/page.html?utm_source=ABC123'; | 120 expect(() { |
| 62 var scriptName = '/assets/static'; | 121 new Request('GET', Uri.parse('http://localhost/dir/test'), |
| 63 var fullUrl = 'http://localhost/other_path/other_resource.asp'; | 122 url: Uri.parse('dir')); |
| 64 var request = new Request('GET', Uri.parse(fullUrl), | 123 }, throwsArgumentError); |
| 65 url: Uri.parse(pathInfo), scriptName: scriptName); | 124 }); |
| 66 | 125 |
| 67 expect(request.scriptName, scriptName); | 126 test('must have the same query parameters as requestedUri', () { |
| 68 expect(request.url.path, '/pages/page.html'); | 127 expect(() { |
| 69 expect(request.url.query, 'utm_source=ABC123'); | 128 new Request('GET', Uri.parse('http://localhost/test?q=1&r=2'), |
| 70 }); | 129 url: Uri.parse('test?q=2&r=1')); |
| 130 }, throwsArgumentError); |
| 71 | 131 |
| 72 test('minimal uri', () { | 132 // Order matters for query parameters. |
| 73 var pathInfo = '/'; | 133 expect(() { |
| 74 var scriptName = '/assets/static'; | 134 new Request('GET', Uri.parse('http://localhost/test?q=1&r=2'), |
| 75 var fullUrl = 'http://localhost$scriptName$pathInfo'; | 135 url: Uri.parse('test?r=2&q=1')); |
| 76 var request = new Request('GET', Uri.parse(fullUrl), | 136 }, throwsArgumentError); |
| 77 url: Uri.parse(pathInfo), scriptName: scriptName); | 137 }); |
| 138 }); |
| 78 | 139 |
| 79 expect(request.scriptName, scriptName); | 140 group('handlerPath', () { |
| 80 expect(request.url.path, '/'); | 141 test('must be a prefix of requestedUri', () { |
| 81 expect(request.url.query, ''); | 142 expect(() { |
| 82 }); | 143 new Request('GET', Uri.parse('http://localhost/dir/test'), |
| 144 handlerPath: '/test'); |
| 145 }, throwsArgumentError); |
| 146 }); |
| 83 | 147 |
| 84 test('invalid url', () { | 148 test('must start with "/"', () { |
| 85 var testUrl = 'page'; | 149 expect(() { |
| 86 var scriptName = '/assets/static'; | 150 new Request('GET', Uri.parse('http://localhost/test'), |
| 87 var fullUrl = 'http://localhost$scriptName$testUrl'; | 151 handlerPath: 'test'); |
| 152 }, throwsArgumentError); |
| 153 }); |
| 154 }); |
| 88 | 155 |
| 89 expect(() => new Request('GET', Uri.parse(fullUrl), | 156 group('handlerPath + url must', () { |
| 90 url: Uri.parse(testUrl), scriptName: scriptName), | 157 test('be requestedUrl path', () { |
| 91 throwsArgumentError); | 158 expect(() { |
| 92 }); | 159 new Request('GET', Uri.parse('http://localhost/foo/bar/baz'), |
| 160 handlerPath: '/foo/', url: Uri.parse('baz')); |
| 161 }, throwsArgumentError); |
| 162 }); |
| 93 | 163 |
| 94 test('scriptName with no leading slash', () { | 164 test('be on a path boundary', () { |
| 95 var pathInfo = '/page'; | 165 expect(() { |
| 96 var scriptName = 'assets/static'; | 166 new Request('GET', Uri.parse('http://localhost/foo/bar/baz'), |
| 97 var fullUrl = 'http://localhost/assets/static/pages'; | 167 handlerPath: '/foo/ba', url: Uri.parse('r/baz')); |
| 98 | 168 }, throwsArgumentError); |
| 99 expect(() => new Request('GET', Uri.parse(fullUrl), | 169 }); |
| 100 url: Uri.parse(pathInfo), scriptName: scriptName), | 170 }); |
| 101 throwsArgumentError); | |
| 102 | |
| 103 pathInfo = '/assets/static/page'; | |
| 104 scriptName = '/'; | |
| 105 fullUrl = 'http://localhost/assets/static/pages'; | |
| 106 | |
| 107 expect(() => new Request('GET', Uri.parse(fullUrl), | |
| 108 url: Uri.parse(pathInfo), scriptName: scriptName), | |
| 109 throwsArgumentError); | |
| 110 }); | |
| 111 | |
| 112 test('scriptName that is only a slash', () { | |
| 113 var pathInfo = '/assets/static/page'; | |
| 114 var scriptName = '/'; | |
| 115 var fullUrl = 'http://localhost/assets/static/pages'; | |
| 116 | |
| 117 expect(() => new Request('GET', Uri.parse(fullUrl), | |
| 118 url: Uri.parse(pathInfo), scriptName: scriptName), | |
| 119 throwsArgumentError); | |
| 120 }); | 171 }); |
| 121 }); | 172 }); |
| 122 | 173 |
| 123 group("ifModifiedSince", () { | 174 group("ifModifiedSince", () { |
| 124 test("is null without an If-Modified-Since header", () { | 175 test("is null without an If-Modified-Since header", () { |
| 125 var request = _request(); | 176 var request = _request(); |
| 126 expect(request.ifModifiedSince, isNull); | 177 expect(request.ifModifiedSince, isNull); |
| 127 }); | 178 }); |
| 128 | 179 |
| 129 test("comes from the Last-Modified header", () { | 180 test("comes from the Last-Modified header", () { |
| 130 var request = _request( | 181 var request = _request( |
| 131 headers: {'if-modified-since': 'Sun, 06 Nov 1994 08:49:37 GMT'}); | 182 headers: {'if-modified-since': 'Sun, 06 Nov 1994 08:49:37 GMT'}); |
| 132 expect(request.ifModifiedSince, | 183 expect(request.ifModifiedSince, |
| 133 equals(DateTime.parse("1994-11-06 08:49:37z"))); | 184 equals(DateTime.parse("1994-11-06 08:49:37z"))); |
| 134 }); | 185 }); |
| 135 }); | 186 }); |
| 136 | 187 |
| 137 group('change', () { | 188 group('change', () { |
| 138 test('with no arguments returns instance with equal values', () { | 189 test('with no arguments returns instance with equal values', () { |
| 139 var controller = new StreamController(); | 190 var controller = new StreamController(); |
| 140 | 191 |
| 141 var uri = Uri.parse('https://test.example.com/static/file.html'); | 192 var uri = Uri.parse('https://test.example.com/static/file.html'); |
| 142 | 193 |
| 143 var request = new Request('GET', uri, | 194 var request = new Request('GET', uri, |
| 144 protocolVersion: '2.0', | 195 protocolVersion: '2.0', |
| 145 headers: {'header1': 'header value 1'}, | 196 headers: {'header1': 'header value 1'}, |
| 146 url: Uri.parse('/file.html'), | 197 url: Uri.parse('file.html'), |
| 147 scriptName: '/static', | 198 handlerPath: '/static/', |
| 148 body: controller.stream, | 199 body: controller.stream, |
| 149 context: {'context1': 'context value 1'}); | 200 context: {'context1': 'context value 1'}); |
| 150 | 201 |
| 151 var copy = request.change(); | 202 var copy = request.change(); |
| 152 | 203 |
| 153 expect(copy.method, request.method); | 204 expect(copy.method, request.method); |
| 154 expect(copy.requestedUri, request.requestedUri); | 205 expect(copy.requestedUri, request.requestedUri); |
| 155 expect(copy.protocolVersion, request.protocolVersion); | 206 expect(copy.protocolVersion, request.protocolVersion); |
| 156 expect(copy.headers, same(request.headers)); | 207 expect(copy.headers, same(request.headers)); |
| 157 expect(copy.url, request.url); | 208 expect(copy.url, request.url); |
| 158 expect(copy.scriptName, request.scriptName); | 209 expect(copy.handlerPath, request.handlerPath); |
| 159 expect(copy.context, same(request.context)); | 210 expect(copy.context, same(request.context)); |
| 160 expect(copy.readAsString(), completion('hello, world')); | 211 expect(copy.readAsString(), completion('hello, world')); |
| 161 | 212 |
| 162 controller.add(HELLO_BYTES); | 213 controller.add(HELLO_BYTES); |
| 163 return new Future(() { | 214 return new Future(() { |
| 164 controller | 215 controller |
| 165 ..add(WORLD_BYTES) | 216 ..add(WORLD_BYTES) |
| 166 ..close(); | 217 ..close(); |
| 167 }); | 218 }); |
| 168 }); | 219 }); |
| 169 | 220 |
| 170 group('with just scriptName', () { | 221 group('with path', () { |
| 171 test('updates url if scriptName matches existing url', () { | 222 test('updates handlerPath and url', () { |
| 172 var uri = Uri.parse('https://test.example.com/static/file.html'); | 223 var uri = Uri.parse('https://test.example.com/static/dir/file.html'); |
| 173 var request = new Request('GET', uri); | 224 var request = new Request('GET', uri, |
| 174 var copy = request.change(scriptName: '/static'); | 225 handlerPath: '/static/', url: Uri.parse('dir/file.html')); |
| 226 var copy = request.change(path: 'dir'); |
| 175 | 227 |
| 176 expect(copy.scriptName, '/static'); | 228 expect(copy.handlerPath, '/static/dir/'); |
| 177 expect(copy.url, Uri.parse('/file.html')); | 229 expect(copy.url, Uri.parse('file.html')); |
| 178 }); | 230 }); |
| 179 | 231 |
| 180 test('throws if striptName does not match existing url', () { | 232 test('allows a trailing slash', () { |
| 181 var uri = Uri.parse('https://test.example.com/static/file.html'); | 233 var uri = Uri.parse('https://test.example.com/static/dir/file.html'); |
| 182 var request = new Request('GET', uri); | 234 var request = new Request('GET', uri, |
| 235 handlerPath: '/static/', url: Uri.parse('dir/file.html')); |
| 236 var copy = request.change(path: 'dir/'); |
| 183 | 237 |
| 184 expect(() => request.change(scriptName: '/nope'), throwsArgumentError); | 238 expect(copy.handlerPath, '/static/dir/'); |
| 239 expect(copy.url, Uri.parse('file.html')); |
| 185 }); | 240 }); |
| 186 }); | |
| 187 | 241 |
| 188 test('url', () { | 242 test('throws if path does not match existing uri', () { |
| 189 var uri = Uri.parse('https://test.example.com/static/file.html'); | 243 var uri = Uri.parse('https://test.example.com/static/dir/file.html'); |
| 190 var request = new Request('GET', uri); | 244 var request = new Request('GET', uri, |
| 191 var copy = request.change(url: Uri.parse('/other_path/file.html')); | 245 handlerPath: '/static/', url: Uri.parse('dir/file.html')); |
| 192 | 246 |
| 193 expect(copy.scriptName, ''); | 247 expect(() => request.change(path: 'wrong'), throwsArgumentError); |
| 194 expect(copy.url, Uri.parse('/other_path/file.html')); | 248 }); |
| 195 }); | |
| 196 | 249 |
| 197 test('scriptName and url', () { | 250 test("throws if path isn't a path boundary", () { |
| 198 var uri = Uri.parse('https://test.example.com/static/file.html'); | 251 var uri = Uri.parse('https://test.example.com/static/dir/file.html'); |
| 199 var request = new Request('GET', uri); | 252 var request = new Request('GET', uri, |
| 200 var copy = request.change( | 253 handlerPath: '/static/', url: Uri.parse('dir/file.html')); |
| 201 scriptName: '/dynamic', url: Uri.parse('/other_path/file.html')); | |
| 202 | 254 |
| 203 expect(copy.scriptName, '/dynamic'); | 255 expect(() => request.change(path: 'di'), throwsArgumentError); |
| 204 expect(copy.url, Uri.parse('/other_path/file.html')); | 256 }); |
| 205 }); | 257 }); |
| 206 }); | 258 }); |
| 207 } | 259 } |
| OLD | NEW |