// 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';
import 'dart:uri';

// 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 = "127.0.0.1",
      int port = 0, int backlog = 0]) {
    return HttpServer.bind(host, port, 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(AsyncError error), void onDone(),
      bool unsubscribeOnError: false}) {
    var subscription;
    subscription = super.listen((request) {
      onData(new _HttpRequestWrapper(request));
    }, onError: (e) {
      var error = e.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 SocketIOException && error.osError.errorCode == 104) return;
      // Ignore any parsing errors, which come from malformed requests.
      if (error is HttpParserException) return;
      // Manually handle unsubscribeOnError so the above (ignored) errors don't
      // cause unsubscription.
      if (unsubscribeOnError) subscription.cancel();
      if (onError != null) onError(e);
    }, 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;
  Map<String, String> get queryParameters => _inner.queryParameters;
  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 writeBytes(List<int> data) => _inner.writeBytes(data);
  Future<HttpResponse> consume(Stream<List<int>> stream) =>
    _inner.consume(stream);
  Future<HttpResponse> writeStream(Stream<List<int>> stream) =>
    _inner.writeStream(stream);
  void close() => _inner.close();
  void write(Object obj) => _inner.write(obj);
  void writeAll(Iterable objects) => _inner.writeAll(objects);
  void writeCharCode(int charCode) => _inner.writeCharCode(charCode);
  void writeln([Object obj = ""]) => _inner.writeln(obj);
}
