// 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.

library safe_http_server;

import 'dart:async';
import 'dart:io';

// TODO(nweiz): remove this when issue 9140 is fixed.
/// A wrapper around [HttpServer] that swallows errors caused by requests
/// behaving badly. This provides the following guarantees:
///
/// * The [SafeHttpServer.listen] onError callback will only emit server-wide
///   errors. It will not emit errors for requests that were unparseable or
///   where the connection was closed too soon.
/// * [HttpResponse.done] will emit no errors.
///
/// The [HttpRequest] data stream can still emit errors.
class SafeHttpServer extends StreamView<HttpRequest> implements HttpServer {
  final HttpServer _inner;

  static Future<SafeHttpServer> bind([String host = "localhost",
      int port = 0, int backlog = 0]) {
    return HttpServer.bind(host, port, backlog: backlog)
        .then((server) => new SafeHttpServer(server));
  }

  SafeHttpServer(HttpServer server)
      : super(server),
        _inner = server;

  void close() => _inner.close();

  int get port => _inner.port;

  set sessionTimeout(int timeout) {
    _inner.sessionTimeout = timeout;
  }

  HttpConnectionsInfo connectionsInfo() => _inner.connectionsInfo();

  StreamSubscription<HttpRequest> listen(void onData(HttpRequest value),
      {void onError(error), void onDone(),
      bool cancelOnError: false}) {
    var subscription;
    subscription = super.listen((request) {
      onData(new _HttpRequestWrapper(request));
    }, onError: (error) {
      // Ignore socket error 104, which is caused by a request being cancelled
      // before it writes any headers. There's no reason to care about such
      // requests.
      if (error is SocketException && error.osError.errorCode == 104) return;
      // Ignore any parsing errors, which come from malformed requests.
      if (error is HttpException) return;
      // Manually handle cancelOnError so the above (ignored) errors don't
      // cause unsubscription.
      if (cancelOnError) subscription.cancel();
      if (onError != null) onError(error);
    }, onDone: onDone);
    return subscription;
  }
}

/// A wrapper around [HttpRequest] for the sole purpose of swallowing errors on
/// [HttpResponse.done].
class _HttpRequestWrapper extends StreamView<List<int>> implements HttpRequest {
  final HttpRequest _inner;
  final HttpResponse response;

  _HttpRequestWrapper(HttpRequest inner)
      : super(inner),
        _inner = inner,
        response = new _HttpResponseWrapper(inner.response);

  int get contentLength => _inner.contentLength;
  String get method => _inner.method;
  Uri get uri => _inner.uri;
  HttpHeaders get headers => _inner.headers;
  List<Cookie> get cookies => _inner.cookies;
  bool get persistentConnection => _inner.persistentConnection;
  X509Certificate get certificate => _inner.certificate;
  HttpSession get session => _inner.session;
  String get protocolVersion => _inner.protocolVersion;
  HttpConnectionInfo get connectionInfo => _inner.connectionInfo;
}

/// A wrapper around [HttpResponse] for the sole purpose of swallowing errors on
/// [done].
class _HttpResponseWrapper implements HttpResponse {
  final HttpResponse _inner;
  Future<HttpResponse> _done;

  _HttpResponseWrapper(this._inner);

  /// Swallows all errors from writing to the response.
  Future<HttpResponse> get done {
    if (_done == null) _done = _inner.done.catchError((_) {});
    return _done;
  }

  int get contentLength => _inner.contentLength;
  set contentLength(int value) {
    _inner.contentLength = value;
  }

  int get statusCode => _inner.statusCode;
  set statusCode(int value) {
    _inner.statusCode = value;
  }

  String get reasonPhrase => _inner.reasonPhrase;
  set reasonPhrase(String value) {
    _inner.reasonPhrase = value;
  }

  bool get persistentConnection => _inner.persistentConnection;
  set persistentConnection(bool value) {
    _inner.persistentConnection = value;
  }

  Encoding get encoding => _inner.encoding;
  set encoding(Encoding value) {
    _inner.encoding = value;
  }

  HttpHeaders get headers => _inner.headers;
  List<Cookie> get cookies => _inner.cookies;
  Future<Socket> detachSocket() => _inner.detachSocket();
  HttpConnectionInfo get connectionInfo => _inner.connectionInfo;
  void add(List<int> data) => _inner.add(data);
  Future<HttpResponse> addStream(Stream<List<int>> stream) =>
    _inner.addStream(stream);
  Future close() => _inner.close();
  void write(Object obj) => _inner.write(obj);
  void writeAll(Iterable objects, [String separator = ""]) =>
    _inner.writeAll(objects, separator);
  void writeCharCode(int charCode) => _inner.writeCharCode(charCode);
  void writeln([Object obj = ""]) => _inner.writeln(obj);
  void addError(error) => _inner.addError(error);
}
