| 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 and [url] is not, [scriptName] must be a |
| 175 /// prefix of [this.url]. [url] will default to [this.url] with this prefix |
| 176 /// removed. Useful for routing middleware that sends requests to an inner |
| 177 /// [Handler]. |
| 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 ' be a prefix of the existing url path.'); |
| 191 } |
| 192 } |
| 193 |
| 194 if (url == null) url = this.url; |
| 195 if (scriptName == null) scriptName = this.scriptName; |
| 196 |
| 175 return new Request(this.method, this.requestedUri, | 197 return new Request(this.method, this.requestedUri, |
| 176 protocolVersion: this.protocolVersion, headers: headers, url: this.url, | 198 protocolVersion: this.protocolVersion, headers: headers, url: url, |
| 177 scriptName: this.scriptName, body: this.read(), context: context); | 199 scriptName: scriptName, body: this.read(), context: context); |
| 178 } | 200 } |
| 179 | 201 |
| 180 /// Takes control of the underlying request socket. | 202 /// Takes control of the underlying request socket. |
| 181 /// | 203 /// |
| 182 /// Synchronously, this throws a [HijackException] that indicates to the | 204 /// Synchronously, this throws a [HijackException] that indicates to the |
| 183 /// adapter that it shouldn't emit a response itself. Asynchronously, | 205 /// adapter that it shouldn't emit a response itself. Asynchronously, |
| 184 /// [callback] is called with a [Stream<List<int>>] and | 206 /// [callback] is called with a [Stream<List<int>>] and |
| 185 /// [StreamSink<List<int>>], respectively, that provide access to the | 207 /// [StreamSink<List<int>>], respectively, that provide access to the |
| 186 /// underlying request socket. | 208 /// underlying request socket. |
| 187 /// | 209 /// |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 248 |
| 227 /// Computes `url` from the provided [Request] constructor arguments. | 249 /// Computes `url` from the provided [Request] constructor arguments. |
| 228 /// | 250 /// |
| 229 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], | 251 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], |
| 230 /// otherwise return [url]. | 252 /// otherwise return [url]. |
| 231 /// | 253 /// |
| 232 /// If [url] is provided, but [scriptName] is omitted, throws an | 254 /// If [url] is provided, but [scriptName] is omitted, throws an |
| 233 /// [ArgumentError]. | 255 /// [ArgumentError]. |
| 234 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { | 256 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { |
| 235 if (url == null && scriptName == null) { | 257 if (url == null && scriptName == null) { |
| 236 return new Uri(path: requestedUri.path, query: requestedUri.query, | 258 return new Uri(path: requestedUri.path, query: requestedUri.query); |
| 237 fragment: requestedUri.fragment); | |
| 238 } | 259 } |
| 239 | 260 |
| 240 if (url != null && scriptName != null) { | 261 if (url != null && scriptName != null) { |
| 241 if (url.scheme.isNotEmpty) throw new ArgumentError('url must be relative.'); | 262 if (url.scheme.isNotEmpty) throw new ArgumentError('url must be relative.'); |
| 242 return url; | 263 return url; |
| 243 } | 264 } |
| 244 | 265 |
| 245 throw new ArgumentError( | 266 throw new ArgumentError( |
| 246 'url and scriptName must both be null or both be set.'); | 267 'url and scriptName must both be null or both be set.'); |
| 247 } | 268 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 258 return ''; | 279 return ''; |
| 259 } | 280 } |
| 260 | 281 |
| 261 if (url != null && scriptName != null) { | 282 if (url != null && scriptName != null) { |
| 262 return scriptName; | 283 return scriptName; |
| 263 } | 284 } |
| 264 | 285 |
| 265 throw new ArgumentError( | 286 throw new ArgumentError( |
| 266 'url and scriptName must both be null or both be set.'); | 287 'url and scriptName must both be null or both be set.'); |
| 267 } | 288 } |
| OLD | NEW |