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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 Stream<List<int>> body, Map<String, Object> context}) | 74 Stream<List<int>> body, Map<String, Object> context}) |
75 : this.requestedUri = requestedUri, | 75 : this.requestedUri = requestedUri, |
76 this.protocolVersion = protocolVersion == null ? | 76 this.protocolVersion = protocolVersion == null ? |
77 '1.1' : protocolVersion, | 77 '1.1' : protocolVersion, |
78 this.url = _computeUrl(requestedUri, url, scriptName), | 78 this.url = _computeUrl(requestedUri, url, scriptName), |
79 this.scriptName = _computeScriptName(requestedUri, url, scriptName), | 79 this.scriptName = _computeScriptName(requestedUri, url, scriptName), |
80 super(body == null ? new Stream.fromIterable([]) : body, | 80 super(body == null ? new Stream.fromIterable([]) : body, |
81 headers: headers, context: context) { | 81 headers: headers, context: context) { |
82 if (method.isEmpty) throw new ArgumentError('method cannot be empty.'); | 82 if (method.isEmpty) throw new ArgumentError('method cannot be empty.'); |
83 | 83 |
84 // TODO(kevmoo) use isAbsolute property on Uri once Issue 18053 is fixed | 84 // NOTE: A Uri with a #fragment is is not considered 'absolute' per |
85 // http://tools.ietf.org/html/rfc3986#section-4.3 | |
86 // So instead of using Uri.isAbsolute, just checking for an empty scheme | |
nweiz
2014/04/28 22:13:33
Use full sentences in comments.
kevmoo
2014/04/29 10:41:54
Done.
| |
85 if (requestedUri.scheme.isEmpty) { | 87 if (requestedUri.scheme.isEmpty) { |
kevmoo
2014/04/26 16:34:34
The RFC is a bit weird about fragments, hence Uri.
nweiz
2014/04/28 22:13:33
I think we should use [isAbsolute] here. The reque
kevmoo
2014/04/29 10:41:54
I double checked. dart_io doesn't send the fragmen
| |
86 throw new ArgumentError('requstedUri must be an absolute URI.'); | 88 throw new ArgumentError('requstedUri must be an absolute URI.'); |
87 } | 89 } |
88 | 90 |
89 if (this.scriptName.isNotEmpty && !this.scriptName.startsWith('/')) { | 91 if (this.scriptName.isNotEmpty && !this.scriptName.startsWith('/')) { |
90 throw new ArgumentError('scriptName must be empty or start with "/".'); | 92 throw new ArgumentError('scriptName must be empty or start with "/".'); |
91 } | 93 } |
92 | 94 |
93 if (this.scriptName == '/') { | 95 if (this.scriptName == '/') { |
94 throw new ArgumentError( | 96 throw new ArgumentError( |
95 'scriptName can never be "/". It should be empty instead.'); | 97 'scriptName can never be "/". It should be empty instead.'); |
96 } | 98 } |
97 | 99 |
98 if (this.scriptName.endsWith('/')) { | 100 if (this.scriptName.endsWith('/')) { |
99 throw new ArgumentError('scriptName must not end with "/".'); | 101 throw new ArgumentError('scriptName must not end with "/".'); |
100 } | 102 } |
101 | 103 |
102 if (this.url.path.isNotEmpty && !this.url.path.startsWith('/')) { | 104 if (this.url.path.isNotEmpty && !this.url.path.startsWith('/')) { |
103 throw new ArgumentError('url must be empty or start with "/".'); | 105 throw new ArgumentError('url must be empty or start with "/".'); |
104 } | 106 } |
105 | 107 |
106 if (this.scriptName.isEmpty && this.url.path.isEmpty) { | 108 if (this.scriptName.isEmpty && this.url.path.isEmpty) { |
107 throw new ArgumentError('scriptName and url cannot both be empty.'); | 109 throw new ArgumentError('scriptName and url cannot both be empty.'); |
108 } | 110 } |
109 } | 111 } |
112 | |
113 /// Copies the request updated [context] and [headers] values. | |
nweiz
2014/04/28 22:13:33
Fix this sentence.
kevmoo
2014/04/29 10:41:54
Done.
| |
114 /// | |
115 /// New key-value pairs in [context] and [headers] will be added to the copied | |
116 /// [Request]. | |
117 /// | |
118 /// If [context] or [headers] includes a key that already exists, the | |
119 /// key-value pair will replace the corresponding entry in the copied | |
120 /// [Request]. | |
121 /// | |
122 /// All other context and header values from the [Request] will be included | |
123 /// in the copied [Request] unchanged. | |
124 Request copy({Map<String, String> headers, Map<String, Object> context}) { | |
nweiz
2014/04/28 22:13:33
We should discuss this name a bit. I like "copy" o
kevmoo
2014/04/29 10:41:54
Done.
| |
125 headers = _updatedMap(this.headers, headers); | |
126 context = _updatedMap(this.context, context); | |
127 | |
128 return new Request(this.method, this.requestedUri, | |
129 protocolVersion: this.protocolVersion, headers: headers, url: this.url, | |
130 scriptName: this.scriptName, body: this.read(), context: context); | |
nweiz
2014/04/28 22:13:33
I don't like that this copies the headers and re-w
kevmoo
2014/04/29 10:41:54
Done.
| |
131 } | |
132 } | |
133 | |
134 Map _updatedMap(Map original, Map updates) { | |
nweiz
2014/04/28 22:13:33
Functions should have verb names, e.g. "_updateMap
kevmoo
2014/04/29 10:41:54
Done.
| |
135 if (updates == null || updates.isEmpty) return original; | |
136 | |
137 return new Map.from(original) | |
138 ..addAll(updates); | |
110 } | 139 } |
111 | 140 |
112 /// Computes `url` from the provided [Request] constructor arguments. | 141 /// Computes `url` from the provided [Request] constructor arguments. |
113 /// | 142 /// |
114 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], | 143 /// If [url] and [scriptName] are `null`, infer value from [requestedUrl], |
115 /// otherwise return [url]. | 144 /// otherwise return [url]. |
116 /// | 145 /// |
117 /// If [url] is provided, but [scriptName] is omitted, throws an | 146 /// If [url] is provided, but [scriptName] is omitted, throws an |
118 /// [ArgumentError]. | 147 /// [ArgumentError]. |
119 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { | 148 Uri _computeUrl(Uri requestedUri, Uri url, String scriptName) { |
(...skipping 24 matching lines...) Expand all Loading... | |
144 return ''; | 173 return ''; |
145 } | 174 } |
146 | 175 |
147 if (url != null && scriptName != null) { | 176 if (url != null && scriptName != null) { |
148 return scriptName; | 177 return scriptName; |
149 } | 178 } |
150 | 179 |
151 throw new ArgumentError( | 180 throw new ArgumentError( |
152 'url and scriptName must both be null or both be set.'); | 181 'url and scriptName must both be null or both be set.'); |
153 } | 182 } |
OLD | NEW |