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.response; | 5 library shelf.response; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 | 9 |
10 import 'package:http_parser/http_parser.dart'; | 10 import 'package:http_parser/http_parser.dart'; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 /// This indicates that the request has succeeded. | 46 /// This indicates that the request has succeeded. |
47 /// | 47 /// |
48 /// [body] is the response body. It may be either a [String], a | 48 /// [body] is the response body. It may be either a [String], a |
49 /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String], | 49 /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String], |
50 /// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to | 50 /// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to |
51 /// UTF-8. | 51 /// UTF-8. |
52 /// | 52 /// |
53 /// If [encoding] is passed, the "encoding" field of the Content-Type header | 53 /// If [encoding] is passed, the "encoding" field of the Content-Type header |
54 /// in [headers] will be set appropriately. If there is no existing | 54 /// in [headers] will be set appropriately. If there is no existing |
55 /// Content-Type header, it will be set to "application/octet-stream". | 55 /// Content-Type header, it will be set to "application/octet-stream". |
56 Response.ok(body, {Map<String, String> headers, Encoding encoding, | 56 Response.ok(body, {Map<String, String> headers, Encoding encoding, |
57 Map<String, Object> context}) | 57 Map<String, Object> context}) |
58 : this(200, body: body, headers: headers, encoding: encoding, | 58 : this(200, body: body, headers: headers, encoding: encoding, |
59 context: context); | 59 context: context); |
60 | 60 |
61 /// Constructs a 301 Moved Permanently response. | 61 /// Constructs a 301 Moved Permanently response. |
62 /// | 62 /// |
63 /// This indicates that the requested resource has moved permanently to a new | 63 /// This indicates that the requested resource has moved permanently to a new |
64 /// URI. [location] is that URI; it can be either a [String] or a [Uri]. It's | 64 /// URI. [location] is that URI; it can be either a [String] or a [Uri]. It's |
65 /// automatically set as the Location header in [headers]. | 65 /// automatically set as the Location header in [headers]. |
66 /// | 66 /// |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 /// If [encoding] is passed, the "encoding" field of the Content-Type header | 111 /// If [encoding] is passed, the "encoding" field of the Content-Type header |
112 /// in [headers] will be set appropriately. If there is no existing | 112 /// in [headers] will be set appropriately. If there is no existing |
113 /// Content-Type header, it will be set to "application/octet-stream". | 113 /// Content-Type header, it will be set to "application/octet-stream". |
114 Response.seeOther(location, {body, Map<String, String> headers, | 114 Response.seeOther(location, {body, Map<String, String> headers, |
115 Encoding encoding, Map<String, Object> context}) | 115 Encoding encoding, Map<String, Object> context}) |
116 : this._redirect(303, location, body, headers, encoding, | 116 : this._redirect(303, location, body, headers, encoding, |
117 context: context); | 117 context: context); |
118 | 118 |
119 /// Constructs a helper constructor for redirect responses. | 119 /// Constructs a helper constructor for redirect responses. |
120 Response._redirect(int statusCode, location, body, | 120 Response._redirect(int statusCode, location, body, |
121 Map<String, String> headers, Encoding encoding, | 121 Map<String, String> headers, Encoding encoding, |
122 { Map<String, Object> context }) | 122 { Map<String, Object> context }) |
123 : this(statusCode, | 123 : this(statusCode, |
124 body: body, | 124 body: body, |
125 encoding: encoding, | 125 encoding: encoding, |
126 headers: _addHeader( | 126 headers: _addHeader( |
127 headers, 'location', _locationToString(location)), | 127 headers, 'location', _locationToString(location)), |
128 context: context); | 128 context: context); |
129 | 129 |
130 /// Constructs a 304 Not Modified response. | 130 /// Constructs a 304 Not Modified response. |
131 /// | 131 /// |
132 /// This is used to respond to a conditional GET request that provided | 132 /// This is used to respond to a conditional GET request that provided |
133 /// information used to determine whether the requested resource has changed | 133 /// information used to determine whether the requested resource has changed |
134 /// since the last request. It indicates that the resource has not changed and | 134 /// since the last request. It indicates that the resource has not changed and |
135 /// the old value should be used. | 135 /// the old value should be used. |
136 Response.notModified({Map<String, String> headers, | 136 Response.notModified({Map<String, String> headers, |
137 Map<String, Object> context}) | 137 Map<String, Object> context}) |
138 : this(304, headers: _addHeader( | 138 : this(304, headers: _addHeader( |
139 headers, 'date', formatHttpDate(new DateTime.now())), | 139 headers, 'date', formatHttpDate(new DateTime.now())), |
140 context: context); | 140 context: context); |
141 | 141 |
142 /// Constructs a 403 Forbidden response. | 142 /// Constructs a 403 Forbidden response. |
143 /// | 143 /// |
144 /// This indicates that the server is refusing to fulfill the request. | 144 /// This indicates that the server is refusing to fulfill the request. |
145 /// | 145 /// |
146 /// [body] is the response body. It may be either a [String], a | 146 /// [body] is the response body. It may be either a [String], a |
(...skipping 15 matching lines...) Expand all Loading... |
162 /// requested URI. | 162 /// requested URI. |
163 /// | 163 /// |
164 /// [body] is the response body. It may be either a [String], a | 164 /// [body] is the response body. It may be either a [String], a |
165 /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String], | 165 /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String], |
166 /// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to | 166 /// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to |
167 /// UTF-8. | 167 /// UTF-8. |
168 /// | 168 /// |
169 /// If [encoding] is passed, the "encoding" field of the Content-Type header | 169 /// If [encoding] is passed, the "encoding" field of the Content-Type header |
170 /// in [headers] will be set appropriately. If there is no existing | 170 /// in [headers] will be set appropriately. If there is no existing |
171 /// Content-Type header, it will be set to "application/octet-stream". | 171 /// Content-Type header, it will be set to "application/octet-stream". |
172 Response.notFound(body, {Map<String, String> headers, Encoding encoding, | 172 Response.notFound(body, {Map<String, String> headers, Encoding encoding, |
173 Map<String, Object> context}) | 173 Map<String, Object> context}) |
174 : this(404, body: body, headers: headers, | 174 : this(404, body: body, headers: headers, |
175 context: context); | 175 context: context); |
176 | 176 |
177 /// Constructs a 500 Internal Server Error response. | 177 /// Constructs a 500 Internal Server Error response. |
178 /// | 178 /// |
179 /// This indicates that the server had an internal error that prevented it | 179 /// This indicates that the server had an internal error that prevented it |
180 /// from fulfilling the request. | 180 /// from fulfilling the request. |
181 /// | 181 /// |
182 /// [body] is the response body. It may be either a [String], a | 182 /// [body] is the response body. It may be either a [String], a |
(...skipping 25 matching lines...) Expand all Loading... |
208 /// Content-Type header, it will be set to "application/octet-stream". | 208 /// Content-Type header, it will be set to "application/octet-stream". |
209 Response(this.statusCode, {body, Map<String, String> headers, | 209 Response(this.statusCode, {body, Map<String, String> headers, |
210 Encoding encoding, Map<String, Object> context}) | 210 Encoding encoding, Map<String, Object> context}) |
211 : super(_bodyToStream(body, encoding), | 211 : super(_bodyToStream(body, encoding), |
212 headers: _adjustHeaders(headers, encoding), | 212 headers: _adjustHeaders(headers, encoding), |
213 context: context) { | 213 context: context) { |
214 if (statusCode < 100) { | 214 if (statusCode < 100) { |
215 throw new ArgumentError("Invalid status code: $statusCode."); | 215 throw new ArgumentError("Invalid status code: $statusCode."); |
216 } | 216 } |
217 } | 217 } |
| 218 |
| 219 /// Creates a new [Response] by copying existing values and applying specified |
| 220 /// changes. |
| 221 /// |
| 222 /// New key-value pairs in [context] and [headers] will be added to the copied |
| 223 /// [Response]. |
| 224 /// |
| 225 /// If [context] or [headers] includes a key that already exists, the |
| 226 /// key-value pair will replace the corresponding entry in the copied |
| 227 /// [Response]. |
| 228 /// |
| 229 /// All other context and header values from the [Response] will be included |
| 230 /// in the copied [Response] unchanged. |
| 231 Response change({Map<String, String> headers, Map<String, Object> context}) { |
| 232 headers = updateMap(this.headers, headers); |
| 233 context = updateMap(this.context, context); |
| 234 |
| 235 return new Response(this.statusCode, body: this.read(), headers: headers, |
| 236 context: context); |
| 237 } |
218 } | 238 } |
219 | 239 |
220 /// Converts [body] to a byte stream. | 240 /// Converts [body] to a byte stream. |
221 /// | 241 /// |
222 /// [body] may be either a [String], a [Stream<List<int>>], or `null`. If it's a | 242 /// [body] may be either a [String], a [Stream<List<int>>], or `null`. If it's a |
223 /// [String], [encoding] will be used to convert it to a [Stream<List<int>>]. | 243 /// [String], [encoding] will be used to convert it to a [Stream<List<int>>]. |
224 Stream<List<int>> _bodyToStream(body, Encoding encoding) { | 244 Stream<List<int>> _bodyToStream(body, Encoding encoding) { |
225 if (encoding == null) encoding = UTF8; | 245 if (encoding == null) encoding = UTF8; |
226 if (body == null) return new Stream.fromIterable([]); | 246 if (body == null) return new Stream.fromIterable([]); |
227 if (body is String) return new Stream.fromIterable([encoding.encode(body)]); | 247 if (body is String) return new Stream.fromIterable([encoding.encode(body)]); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 /// Converts [location], which may be a [String] or a [Uri], to a [String]. | 295 /// Converts [location], which may be a [String] or a [Uri], to a [String]. |
276 /// | 296 /// |
277 /// Throws an [ArgumentError] if [location] isn't a [String] or a [Uri]. | 297 /// Throws an [ArgumentError] if [location] isn't a [String] or a [Uri]. |
278 String _locationToString(location) { | 298 String _locationToString(location) { |
279 if (location is String) return location; | 299 if (location is String) return location; |
280 if (location is Uri) return location.toString(); | 300 if (location is Uri) return location.toString(); |
281 | 301 |
282 throw new ArgumentError('Response location must be a String or Uri, was ' | 302 throw new ArgumentError('Response location must be a String or Uri, was ' |
283 '"$location".'); | 303 '"$location".'); |
284 } | 304 } |
OLD | NEW |