// Copyright (c) 2013, 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.

part of http_server;


/**
 * [HttpBodyHandler] is a helper class for processing and collecting
 * HTTP message data in an easy-to-use [HttpBody] object. The content
 * body is parsed, depending on the `Content-Type` header field. When
 * the full body is read and parsed the body content is made
 * available. The class can be used to process both server requests
 * and client responses.
 *
 * The following content types are recognized:
 *
 *     text/\*
 *     application/json
 *     application/x-www-form-urlencoded
 *     multipart/form-data
 *
 *  For content type `text/\*` the body is decoded into a string. The
 *  'charset' parameter of the content type specifies the encoding
 *  used for decoding. If no 'charset' is present the default encoding
 *  of ISO-8859-1 is used.
 *
 *  For content type `application/json` the body is decoded into a
 *  string which is then parsed as JSON. The resulting body is a
 *  [Map].  The 'charset' parameter of the content type specifies the
 *  encoding used for decoding. If no 'charset' is present the default
 *  encoding of UTF-8 is used.
 *
 *  For content type `application/x-www-form-urlencoded` the body is a
 *  query string which is then split according to the rules for
 *  splitting a query string. The resulting body is a `Map<String,
 *  String>`.  If the same name is present several times in the query
 *  string, then the last value seen for this name will be in the
 *  resulting map. The encoding US-ASCII is always used for decoding
 *  the body.
 *
 *  For content type `multipart/form-data` the body is parsed into
 *  it's different fields. The resulting body is a `Map<String,
 *  dynamic>`, where the value is a [String] for normal fields and a
 *  [HttpBodyFileUpload] instance for file upload fields. If the same
 *  name is present several times, then the last value seen for this
 *  name will be in the resulting map.
 *
 *  When using content type `multipart/form-data` the encoding of
 *  fields with [String] values is determined by the browser sending
 *  the HTTP request with the form data. The encoding is specified
 *  either by the attribute `accept-charset` on the HTML form, or by
 *  the content type of the web page containing the form. If the HTML
 *  form has an `accept-charset` attribute the browser will use the
 *  encoding specified there. If the HTML form has no `accept-charset`
 *  attribute the browser determines the encoding from the content
 *  type of the web page containing the form. Using a content type of
 *  `text/html; charset=utf-8` for the page and setting
 *  `accept-charset` on the HTML form to `utf-8` is recommended as the
 *  default for [HttpBodyHandler] is UTF-8. It is important to get
 *  these encoding values right, as the actual `multipart/form-data`
 *  HTTP request sent by the browser does _not_ contain any
 *  information on the encoding. If something else than UTF-8 is used
 *  `defaultEncoding` needs to be set in the [HttpBodyHandler]
 *  constructor and calls to [processRequest] and [processResponse].
 *
 *  For all other content types the body will be treated as
 *  uninterpreted binary data. The resulting body will be of type
 *  `List<int>`.
 *
 * To use with the [HttpServer] for request messages, [HttpBodyHandler] can be
 * used as either a [StreamTransformer] or as a per-request handler (see
 * [processRequest]).
 *
 *     HttpServer server = ...
 *     server.transform(new HttpBodyHandler())
 *         .listen((HttpRequestBody body) {
 *           ...
 *         });
 *
 * To use with the [HttpClient] for response messages, [HttpBodyHandler] can be
 * used as a per-request handler (see [processResponse]).
 *
 *     HttpClient client = ...
 *     client.get(...)
 *         .then((HttpClientRequest response) => response.close())
 *         .then(HttpBodyHandler.processResponse)
 *         .then((HttpClientResponseBody body) {
 *           ...
 *         });
 *
 */
class HttpBodyHandler
    implements StreamTransformer<HttpRequest, HttpRequestBody> {
  var _transformer;

  /**
   * Create a new [HttpBodyHandler] to be used with a [Stream]<[HttpRequest]>,
   * e.g. a [HttpServer].
   *
   * If the page is served using different encoding than UTF-8, set
   * [defaultEncoding] accordingly. This is required for parsing
   * `multipart/form-data` content correctly. See the class comment
   * for more information on `multipart/form-data`.
   */
  HttpBodyHandler({Encoding defaultEncoding: UTF8})
      : _transformer = new _HttpBodyHandlerTransformer(defaultEncoding);

  /**
   * Process and parse an incoming [HttpRequest]. The returned [HttpRequestBody]
   * contains a [response] field for accessing the [HttpResponse].
   *
   * See [HttpBodyHandler] constructor for more info on [defaultEncoding].
   */
  static Future<HttpRequestBody> processRequest(
      HttpRequest request,
      {Encoding defaultEncoding: UTF8}) {
    return _HttpBodyHandler.processRequest(request, defaultEncoding);
  }

  /**
   * Process and parse an incoming [HttpClientResponse].
   *
   * See [HttpBodyHandler] constructor for more info on [defaultEncoding].
   */
  static Future<HttpClientResponseBody> processResponse(
      HttpClientResponse response,
      {Encoding defaultEncoding: UTF8}) {
    return _HttpBodyHandler.processResponse(response, defaultEncoding);
  }

  Stream<HttpRequestBody> bind(Stream<HttpRequest> stream) {
    return _transformer.bind(stream);
  }
}


/**
 * A HTTP content body produced by [HttpBodyHandler] for either [HttpRequest]
 * or [HttpClientResponse].
 */
abstract class HttpBody {
  /**
   * The content type e.g. application/json, application/octet-stream,
   * application/x-www-form-urlencoded, text/plain.
   */
  ContentType get contentType;

  /**
   * A high-level type value, that reflects how the body was parsed, e.g.
   * "text", "binary" and "json".
   */
  String get type;

  /**
   * The actual body. The type depends on [type].
   */
  dynamic get body;
}


/**
 * The [HttpBody] of a [HttpClientResponse] will be of type
 * [HttpClientResponseBody]. It contains the [HttpClientResponse] object
 * for access to the headers.
 */
abstract class HttpClientResponseBody extends HttpBody {
  /**
   * Returns the status code.
   */
  int get statusCode;

  /**
   * Returns the reason phrase associated with the status code.
   */
  String get reasonPhrase;

  /**
   * Returns the response headers.
   */
  HttpHeaders get headers;

  /**
   * The [HttpClientResponse] of the HTTP body.
   */
  HttpClientResponse get response;
}


/**
 * The [HttpBody] of a [HttpRequest] will be of type [HttpRequestBody]. It
 * contains the fields used to read all request header information and
 * responding to the client.
 */
abstract class HttpRequestBody extends HttpBody {
  /**
   * Returns the method for the request.
   */
  String get method;

  /**
   * Returns the URI for the request.
   */
  Uri get uri;

  /**
   * Returns the request headers.
   */
  HttpHeaders get headers;

  /**
   * The [HttpResponse] used for responding to the client.
   */
  HttpResponse get response;
}


/**
 * A [HttpBodyFileUpload] object wraps a file upload, presenting a way for
 * extracting filename, contentType and the data of the uploaded file.
 */
abstract class HttpBodyFileUpload {
  /**
   * The filename of the uploaded file.
   */
  String get filename;

  /**
   * The [ContentType] of the uploaded file. For 'text/\*' and
   * 'application/json' the [data] field will a String.
   */
  ContentType get contentType;

  /**
   * The content of the file. Either a [String] or a [List<int>].
   */
  dynamic get content;
}
