// Copyright (c) 2018, 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:async";

import 'package:http_io/http_io.dart';
import 'package:test/test.dart';

Future<HttpServer> setupServer() {
  return HttpServer.bind("127.0.0.1", 0).then((server) {
    var handlers = new Map<String, Function>();
    addRequestHandler(
        String path, void handler(HttpRequest request, HttpResponse response)) {
      handlers[path] = handler;
    }

    server.listen((HttpRequest request) {
      if (handlers.containsKey(request.uri.path)) {
        handlers[request.uri.path](request, request.response);
      } else {
        request.listen((_) {}, onDone: () {
          request.response.statusCode = 404;
          request.response.close();
        });
      }
    });

    void addRedirectHandler(int number, int statusCode) {
      addRequestHandler("/$number",
          (HttpRequest request, HttpResponse response) {
        response.redirect(
            Uri.parse("http://127.0.0.1:${server.port}/${number + 1}"));
      });
    }

    // Setup simple redirect.
    addRequestHandler("/redirect",
        (HttpRequest request, HttpResponse response) {
      response.redirect(Uri.parse("http://127.0.0.1:${server.port}/location"),
          status: HttpStatus.MOVED_PERMANENTLY);
    });
    addRequestHandler("/location",
        (HttpRequest request, HttpResponse response) {
      response.close();
    });

    // Setup redirects with relative url.
    addRequestHandler("/redirectUrl",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.LOCATION, "/some/relativeUrl");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    addRequestHandler("/some/redirectUrl",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.LOCATION, "relativeUrl");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    addRequestHandler("/some/relativeUrl",
        (HttpRequest request, HttpResponse response) {
      response.close();
    });

    addRequestHandler("/some/relativeToAbsolute",
        (HttpRequest request, HttpResponse response) {
      response.redirect(Uri.parse("xxx"), status: HttpStatus.SEE_OTHER);
    });

    addRequestHandler("/redirectUrl2",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.LOCATION, "location");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    addRequestHandler("/redirectUrl3",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.LOCATION, "./location");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    addRequestHandler("/redirectUrl4",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.LOCATION, "./a/b/../../location");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    addRequestHandler("/redirectUrl5",
        (HttpRequest request, HttpResponse response) {
      response.headers
          .set(HttpHeaders.LOCATION, "//127.0.0.1:${server.port}/location");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });

    // Setup redirect chain.
    int n = 1;
    addRedirectHandler(n++, HttpStatus.MOVED_PERMANENTLY);
    addRedirectHandler(n++, HttpStatus.MOVED_TEMPORARILY);
    addRedirectHandler(n++, HttpStatus.SEE_OTHER);
    addRedirectHandler(n++, HttpStatus.TEMPORARY_REDIRECT);
    for (int i = n; i < 10; i++) {
      addRedirectHandler(i, HttpStatus.MOVED_PERMANENTLY);
    }

    // Setup redirect loop.
    addRequestHandler("/A", (HttpRequest request, HttpResponse response) {
      response.headers
          .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/B");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });
    addRequestHandler("/B", (HttpRequest request, HttpResponse response) {
      response.headers
          .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/A");
      response.statusCode = HttpStatus.MOVED_TEMPORARILY;
      response.close();
    });

    // Setup redirect checking headers.
    addRequestHandler("/src", (HttpRequest request, HttpResponse response) {
      expect("value", equals(request.headers.value("X-Request-Header")));
      response.headers
          .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/target");
      response.statusCode = HttpStatus.MOVED_PERMANENTLY;
      response.close();
    });
    addRequestHandler("/target", (HttpRequest request, HttpResponse response) {
      expect("value", equals(request.headers.value("X-Request-Header")));
      response.close();
    });

    // Setup redirect for 301 where POST should not redirect.
    addRequestHandler("/301src", (HttpRequest request, HttpResponse response) {
      expect("POST", equals(request.method));
      request.listen((_) {}, onDone: () {
        response.headers.set(
            HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/301target");
        response.statusCode = HttpStatus.MOVED_PERMANENTLY;
        response.close();
      });
    });
    addRequestHandler("/301target",
        (HttpRequest request, HttpResponse response) {
      fail("Redirect of POST should not happen");
    });

    // Setup redirect for 303 where POST should turn into GET.
    addRequestHandler("/303src", (HttpRequest request, HttpResponse response) {
      request.listen((_) {}, onDone: () {
        expect("POST", equals(request.method));
        response.headers.set(
            HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/303target");
        response.statusCode = HttpStatus.SEE_OTHER;
        response.close();
      });
    });
    addRequestHandler("/303target",
        (HttpRequest request, HttpResponse response) {
      expect("GET", equals(request.method));
      response.close();
    });

    // Setup redirect where we close the connection.
    addRequestHandler("/closing", (HttpRequest request, HttpResponse response) {
      response.headers
          .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/");
      response.statusCode = HttpStatus.FOUND;
      response.persistentConnection = false;
      response.close();
    });
    return server;
  });
}

void checkRedirects(int redirectCount, HttpClientResponse response) {
  if (redirectCount < 2) {
    expect(response.redirects.isEmpty, isTrue);
  } else {
    expect(redirectCount - 1, equals(response.redirects.length));
    for (int i = 0; i < redirectCount - 2; i++) {
      expect(response.redirects[i].location.path, equals("/${i + 2}"));
    }
  }
}

Future<Null> testManualRedirect() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    int redirectCount = 0;
    handleResponse(HttpClientResponse response) {
      response.listen((_) => fail("Response data not expected"), onDone: () {
        redirectCount++;
        if (redirectCount < 10) {
          expect(response.isRedirect, isTrue);
          checkRedirects(redirectCount, response);
          response.redirect().then(handleResponse);
        } else {
          expect(HttpStatus.NOT_FOUND, equals(response.statusCode));
          server.close();
          client.close();
          completer.complete();
        }
      });
    }

    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
        .then((HttpClientRequest request) {
      request.followRedirects = false;
      return request.close();
    }).then(handleResponse);
  });
  return completer.future;
}

Future<Null> testManualRedirectWithHeaders() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    int redirectCount = 0;

    handleResponse(HttpClientResponse response) {
      response.listen((_) => fail("Response data not expected"), onDone: () {
        redirectCount++;
        if (redirectCount < 2) {
          expect(response.isRedirect, isTrue);
          response.redirect().then(handleResponse);
        } else {
          expect(HttpStatus.OK, equals(response.statusCode));
          server.close();
          client.close();
          completer.complete();
        }
      });
    }

    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/src"))
        .then((HttpClientRequest request) {
      request.followRedirects = false;
      request.headers.add("X-Request-Header", "value");
      return request.close();
    }).then(handleResponse);
  });
  return completer.future;
}

Future<Null> testAutoRedirect() {
  final completer = new Completer<Null>();

  setupServer().then((server) {
    HttpClient client = new HttpClient();

    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/redirect"))
        .then((HttpClientRequest request) {
      return request.close();
    }).then((HttpClientResponse response) {
      response.listen((_) => fail("Response data not expected"), onDone: () {
        expect(1, equals(response.redirects.length));
        server.close();
        client.close();
        completer.complete();
      });
    });
  });
  return completer.future;
}

Future<Null> testAutoRedirectWithHeaders() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/src"))
        .then((HttpClientRequest request) {
      request.headers.add("X-Request-Header", "value");
      return request.close();
    }).then((HttpClientResponse response) {
      response.listen((_) => fail("Response data not expected"), onDone: () {
        expect(1, equals(response.redirects.length));
        server.close();
        client.close();
        completer.complete();
      });
    });
  });
  return completer.future;
}

Future<Null> testAutoRedirect301POST() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    client
        .postUrl(Uri.parse("http://127.0.0.1:${server.port}/301src"))
        .then((HttpClientRequest request) {
      return request.close();
    }).then((HttpClientResponse response) {
      expect(HttpStatus.MOVED_PERMANENTLY, equals(response.statusCode));
      response.listen((_) => fail("Response data not expected"), onDone: () {
        expect(0, equals(response.redirects.length));
        server.close();
        client.close();
        completer.complete();
      });
    });
  });
  return completer.future;
}

Future<Null> testAutoRedirect303POST() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    client
        .postUrl(Uri.parse("http://127.0.0.1:${server.port}/303src"))
        .then((HttpClientRequest request) {
      return request.close();
    }).then((HttpClientResponse response) {
      expect(HttpStatus.OK, equals(response.statusCode));
      response.listen((_) => fail("Response data not expected"), onDone: () {
        expect(1, equals(response.redirects.length));
        server.close();
        client.close();
        completer.complete();
      });
    });
  });
  return completer.future;
}

Future<Null> testAutoRedirectLimit() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();
    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
        .then((HttpClientRequest request) => request.close())
        .catchError((error) {
      expect(5, equals(error.redirects.length));
      server.close();
      client.close();
      completer.complete();
    }, test: (e) => e is RedirectException);
  });
  return completer.future;
}

Future<Null> testRedirectLoop() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();
    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/A"))
        .then((HttpClientRequest request) => request.close())
        .catchError((error) {
      expect(2, equals(error.redirects.length));
      server.close();
      client.close();
      completer.complete();
    }, test: (e) => e is RedirectException);
  });
  return completer.future;
}

Future<Null> testRedirectClosingConnection() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();
    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/closing"))
        .then((request) => request.close())
        .then((response) {
      response.listen((_) {}, onDone: () {
        expect(1, equals(response.redirects.length));
        server.close();
        client.close();
        completer.complete();
      });
    });
  });
  return completer.future;
}

Future<Null> testRedirectRelativeUrl() async {
  Future<Null> testPath(String path) {
    final completer = new Completer<Null>();
    setupServer().then((server) {
      HttpClient client = new HttpClient();
      client
          .getUrl(Uri.parse("http://127.0.0.1:${server.port}$path"))
          .then((request) => request.close())
          .then((response) {
        response.listen((_) {}, onDone: () {
          expect(HttpStatus.OK, equals(response.statusCode));
          expect(1, equals(response.redirects.length));
          server.close();
          client.close();
          completer.complete();
        });
      });
    });
    return completer.future;
  }

  await testPath("/redirectUrl");
  await testPath("/some/redirectUrl");
  await testPath("/redirectUrl2");
  await testPath("/redirectUrl3");
  await testPath("/redirectUrl4");
  await testPath("/redirectUrl5");
}

Future<Null> testRedirectRelativeToAbsolute() {
  final completer = new Completer<Null>();
  setupServer().then((server) {
    HttpClient client = new HttpClient();

    handleResponse(HttpClientResponse response) {
      response.listen((_) => fail("Response data not expected"), onDone: () {
        expect(HttpStatus.SEE_OTHER, equals(response.statusCode));
        expect("xxx", equals(response.headers["Location"][0]));
        expect(response.isRedirect, isTrue);
        server.close();
        client.close();
        completer.complete();
      });
    }

    client
        .getUrl(Uri.parse(
            "http://127.0.0.1:${server.port}/some/relativeToAbsolute"))
        .then((HttpClientRequest request) {
      request.followRedirects = false;
      return request.close();
    }).then(handleResponse);
  });
  return completer.future;
}

main() {
  test('manualRedirect', testManualRedirect);
  test('manualRedirectWithHeaders', testManualRedirectWithHeaders);
  test('autoRedirect', testAutoRedirect);
  test('autoRedirectWithHeaders', testAutoRedirectWithHeaders);
  test('autoRedirect301POST', testAutoRedirect301POST);
  test('autoRedirect303POST', testAutoRedirect303POST);
  test('autoRedirectLimit', testAutoRedirectLimit);
  test('redirectLoop', testRedirectLoop);
  test('redirectClosingConnection', testRedirectClosingConnection);
  test('redirectRelativeUrl', testRedirectRelativeUrl);
  test('redirectRelativeToAbsolute', testRedirectRelativeToAbsolute);
}
