Chromium Code Reviews| 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; | 5 library shelf.request; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:http_parser/http_parser.dart'; | 9 import 'package:http_parser/http_parser.dart'; |
| 10 | 10 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 this.scriptName = _computeScriptName(requestedUri, url, scriptName), | 127 this.scriptName = _computeScriptName(requestedUri, url, scriptName), |
| 128 this._onHijack = onHijack == null ? null : new _OnHijack(onHijack), | 128 this._onHijack = onHijack == null ? null : new _OnHijack(onHijack), |
| 129 super(body == null ? new Stream.fromIterable([]) : body, | 129 super(body == null ? new Stream.fromIterable([]) : body, |
| 130 headers: headers, context: context) { | 130 headers: headers, context: context) { |
| 131 if (method.isEmpty) throw new ArgumentError('method cannot be empty.'); | 131 if (method.isEmpty) throw new ArgumentError('method cannot be empty.'); |
| 132 | 132 |
| 133 if (!requestedUri.isAbsolute) { | 133 if (!requestedUri.isAbsolute) { |
| 134 throw new ArgumentError('requstedUri must be an absolute URI.'); | 134 throw new ArgumentError('requstedUri must be an absolute URI.'); |
| 135 } | 135 } |
| 136 | 136 |
| 137 // TODO(kevmoo) if defined, check that scriptName is a fully-encoded, valid | |
| 138 // path component | |
| 137 if (this.scriptName.isNotEmpty && !this.scriptName.startsWith('/')) { | 139 if (this.scriptName.isNotEmpty && !this.scriptName.startsWith('/')) { |
| 138 throw new ArgumentError('scriptName must be empty or start with "/".'); | 140 throw new ArgumentError('scriptName must be empty or start with "/".'); |
| 139 } | 141 } |
| 140 | 142 |
| 141 if (this.scriptName == '/') { | 143 if (this.scriptName == '/') { |
| 142 throw new ArgumentError( | 144 throw new ArgumentError( |
| 143 'scriptName can never be "/". It should be empty instead.'); | 145 'scriptName can never be "/". It should be empty instead.'); |
| 144 } | 146 } |
| 145 | 147 |
| 146 if (this.scriptName.endsWith('/')) { | 148 if (this.scriptName.endsWith('/')) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 161 /// | 163 /// |
| 162 /// New key-value pairs in [context] and [headers] will be added to the copied | 164 /// New key-value pairs in [context] and [headers] will be added to the copied |
| 163 /// [Request]. | 165 /// [Request]. |
| 164 /// | 166 /// |
| 165 /// If [context] or [headers] includes a key that already exists, the | 167 /// If [context] or [headers] includes a key that already exists, the |
| 166 /// key-value pair will replace the corresponding entry in the copied | 168 /// key-value pair will replace the corresponding entry in the copied |
| 167 /// [Request]. | 169 /// [Request]. |
| 168 /// | 170 /// |
| 169 /// All other context and header values from the [Request] will be included | 171 /// All other context and header values from the [Request] will be included |
| 170 /// in the copied [Request] unchanged. | 172 /// in the copied [Request] unchanged. |
| 171 Request change({Map<String, String> headers, Map<String, Object> context}) { | 173 /// |
| 174 /// If [scriptName] is provided without [url], the corresponding path | |
| 175 /// component of [Request.url] is replaced in the new instance. In this case, | |
| 176 /// [scriptName] must match the beginning of the existing `path` component of | |
| 177 /// [Request.url] or an [ArgumentError] is thrown. | |
|
nweiz
2014/05/22 19:50:42
This paragraph is confusing. I suggest: "If [scrip
kevmoo
2014/05/22 20:38:36
Done.
nweiz
2014/05/23 21:43:34
You didn't include any explanation of the purpose.
| |
| 178 Request change({Map<String, String> headers, Map<String, Object> context, | |
| 179 String scriptName, Uri url}) { | |
| 172 headers = updateMap(this.headers, headers); | 180 headers = updateMap(this.headers, headers); |
| 173 context = updateMap(this.context, context); | 181 context = updateMap(this.context, context); |
| 174 | 182 |
| 183 if (scriptName != null && url == null) { | |
| 184 var path = this.url.path; | |
| 185 if (path.startsWith(scriptName)) { | |
| 186 path = path.substring(scriptName.length); | |
| 187 url = new Uri(path: path, query: this.url.query); | |
| 188 } else { | |
| 189 throw new ArgumentError('If scriptName is provided without url, it must' | |
| 190 ' match the beginning of the existing url path.'); | |
|
nweiz
2014/05/22 19:50:42
"match the beginning" -> "be a prefix"
kevmoo
2014/05/22 20:38:36
Done.
| |
| 191 } | |
| 192 } | |
| 193 | |
| 194 if (url == null) url = this.url; | |
| 195 | |
|
nweiz
2014/05/22 19:50:42
Nit: I'd remove this newline.
kevmoo
2014/05/22 20:38:36
Done.
| |
| 196 if (scriptName == null) scriptName = this.scriptName; | |
| 197 | |
| 175 return new Request(this.method, this.requestedUri, | 198 return new Request(this.method, this.requestedUri, |
| 176 protocolVersion: this.protocolVersion, headers: headers, url: this.url, | 199 protocolVersion: this.protocolVersion, headers: headers, url: url, |
| 177 scriptName: this.scriptName, body: this.read(), context: context); | 200 scriptName: scriptName, body: this.read(), context: context); |
| 178 } | 201 } |
| 179 | 202 |
| 180 /// Takes control of the underlying request socket. | 203 /// Takes control of the underlying request socket. |
| 181 /// | 204 /// |
| 182 /// Synchronously, this throws a [HijackException] that indicates to the | 205 /// Synchronously, this throws a [HijackException] that indicates to the |
| 183 /// adapter that it shouldn't emit a response itself. Asynchronously, | 206 /// adapter that it shouldn't emit a response itself. Asynchronously, |
| 184 /// [callback] is called with a [Stream<List<int>>] and | 207 /// [callback] is called with a [Stream<List<int>>] and |
| 185 /// [StreamSink<List<int>>], respectively, that provide access to the | 208 /// [StreamSink<List<int>>], respectively, that provide access to the |
| 186 /// underlying request socket. | 209 /// underlying request socket. |
| 187 /// | 210 /// |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 | 249 |
| 227 /// Computes `url` from the provided [Request] constructor arguments. | 250 /// Computes `url` from the provided [Request] constructor arguments. |
| 228 /// | 251 /// |
| 229 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], | 252 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], |
| 230 /// otherwise return [url]. | 253 /// otherwise return [url]. |
| 231 /// | 254 /// |
| 232 /// If [url] is provided, but [scriptName] is omitted, throws an | 255 /// If [url] is provided, but [scriptName] is omitted, throws an |
| 233 /// [ArgumentError]. | 256 /// [ArgumentError]. |
| 234 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { | 257 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { |
| 235 if (url == null && scriptName == null) { | 258 if (url == null && scriptName == null) { |
| 236 return new Uri(path: requestedUri.path, query: requestedUri.query, | 259 return new Uri(path: requestedUri.path, query: requestedUri.query); |
| 237 fragment: requestedUri.fragment); | |
| 238 } | 260 } |
| 239 | 261 |
| 240 if (url != null && scriptName != null) { | 262 if (url != null && scriptName != null) { |
| 241 if (url.scheme.isNotEmpty) throw new ArgumentError('url must be relative.'); | 263 if (url.scheme.isNotEmpty) throw new ArgumentError('url must be relative.'); |
| 242 return url; | 264 return url; |
| 243 } | 265 } |
| 244 | 266 |
| 245 throw new ArgumentError( | 267 throw new ArgumentError( |
| 246 'url and scriptName must both be null or both be set.'); | 268 'url and scriptName must both be null or both be set.'); |
| 247 } | 269 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 258 return ''; | 280 return ''; |
| 259 } | 281 } |
| 260 | 282 |
| 261 if (url != null && scriptName != null) { | 283 if (url != null && scriptName != null) { |
| 262 return scriptName; | 284 return scriptName; |
| 263 } | 285 } |
| 264 | 286 |
| 265 throw new ArgumentError( | 287 throw new ArgumentError( |
| 266 'url and scriptName must both be null or both be set.'); | 288 'url and scriptName must both be null or both be set.'); |
| 267 } | 289 } |
| OLD | NEW |