blob: 65b7135d1da885c6661fc44b18f5aff7bcbdcbad [file] [log] [blame] [edit]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
import 'message.dart';
import 'utils.dart';
/// An HTTP response where the entire response body is known in advance.
class Response extends Message {
/// The location of the requested resource.
///
/// The value takes into account any redirects that occurred during the
/// request.
final Uri finalUrl;
/// The status code of the response.
final int statusCode;
/// The reason phrase associated with the status code.
final String reasonPhrase;
/// Creates a new HTTP response for a resource at the [finalUrl], which can
/// be a [Uri] or a [String], with the given [statusCode].
///
/// [body] is the request body. It may be either a [String], a [List<int>], a
/// [Stream<List<int>>], or `null` to indicate no body. If it's a [String],
/// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to
/// UTF-8.
///
/// [headers] are the HTTP headers for the request. If [headers] is `null`,
/// it is treated as empty.
///
/// Extra [context] can be used to pass information between outer middleware
/// and handlers.
Response(finalUrl, int statusCode,
{String reasonPhrase,
body,
Encoding encoding,
Map<String, String> headers,
Map<String, Object> context})
: this._(getUrl(finalUrl), statusCode, reasonPhrase ?? '', body, encoding,
headers, context);
Response._(
this.finalUrl,
this.statusCode,
this.reasonPhrase,
body,
Encoding encoding,
Map<String, String> headers,
Map<String, Object> context)
: super(body, encoding: encoding, headers: headers, context: context);
/// Creates a new [Response] by copying existing values and applying specified
/// changes.
///
/// New key-value pairs in [context] and [headers] will be added to the copied
/// [Response].
///
/// If [context] or [headers] includes a key that already exists, the
/// key-value pair will replace the corresponding entry in the copied
/// [Response].
///
/// All other context and header values from the [Response] will be included
/// in the copied [Response] unchanged.
///
/// [body] is the request body. It may be either a [String], a [List<int>], a
/// [Stream<List<int>>], or `null` to indicate no body.
Response change(
{Map<String, String> headers, Map<String, Object> context, body}) {
var updatedHeaders = updateMap(this.headers, headers);
var updatedContext = updateMap(this.context, context);
return new Response._(finalUrl, statusCode, reasonPhrase,
body ?? getBody(this), encoding, updatedHeaders, updatedContext);
}
/// The date and time after which the response's data should be considered
/// stale.
///
/// This is parsed from the Expires header in [headers]. If [headers] doesn't
/// have an Expires header, this will be `null`.
DateTime get expires {
if (_expiresCache != null) return _expiresCache;
if (!headers.containsKey('expires')) return null;
_expiresCache = parseHttpDate(headers['expires']);
return _expiresCache;
}
DateTime _expiresCache;
/// The date and time the source of the response's data was last modified.
///
/// This is parsed from the Last-Modified header in [headers]. If [headers]
/// doesn't have a Last-Modified header, this will be `null`.
DateTime get lastModified {
if (_lastModifiedCache != null) return _lastModifiedCache;
if (!headers.containsKey('last-modified')) return null;
_lastModifiedCache = parseHttpDate(headers['last-modified']);
return _lastModifiedCache;
}
DateTime _lastModifiedCache;
}