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

import "package:expect/expect.dart";
import "dart:async";
import "dart:io";
import "dart:mirrors";

Future<HttpServer> setupServer({Uri? targetServer}) {
  final completer = new Completer<HttpServer>();
  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.movedPermanently);
    });
    addRequestHandler("/location",
        (HttpRequest request, HttpResponse response) {
      response.close();
    });

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

    addRequestHandler("/some/redirectUrl",
        (HttpRequest request, HttpResponse response) {
      response.headers.set(HttpHeaders.locationHeader, "relativeUrl");
      response.statusCode = HttpStatus.movedPermanently;
      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.seeOther);
    });

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

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

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

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

    // Setup redirect chain.
    int n = 1;
    addRedirectHandler(n++, HttpStatus.movedPermanently);
    addRedirectHandler(n++, HttpStatus.movedTemporarily);
    addRedirectHandler(n++, HttpStatus.seeOther);
    addRedirectHandler(n++, HttpStatus.temporaryRedirect);
    addRedirectHandler(n++, HttpStatus.permanentRedirect);
    for (int i = n; i < 10; i++) {
      addRedirectHandler(i, HttpStatus.movedPermanently);
    }

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

    // Setup redirect checking headers.
    addRequestHandler("/src", (HttpRequest request, HttpResponse response) {
      Expect.equals("value", request.headers.value("X-Request-Header"));
      Expect.isNotNull(request.headers.value("Authorization"),
          "expected 'Authorization' header to be set");
      response.headers.set(
          HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/target");
      response.statusCode = HttpStatus.movedPermanently;
      response.close();
    });
    addRequestHandler("/target", (HttpRequest request, HttpResponse response) {
      Expect.equals("value", request.headers.value("X-Request-Header"));
      Expect.isNotNull(request.headers.value("Authorization"),
          "expected 'Authorization' header to be set");
      response.close();
    });

    if (targetServer != null) {
      addRequestHandler("/src-crossdomain",
          (HttpRequest request, HttpResponse response) {
        Expect.equals("value", request.headers.value("X-Request-Header"));
        Expect.isNotNull(request.headers.value("Authorization"),
            "expected 'Authorization' header to be set");
        response.headers
            .set(HttpHeaders.locationHeader, targetServer.toString());
        response.statusCode = HttpStatus.movedPermanently;
        response.close();
      });
    }

    // Setup redirect for 301 where POST should not redirect.
    addRequestHandler("/301src", (HttpRequest request, HttpResponse response) {
      Expect.equals("POST", request.method);
      request.listen((_) {}, onDone: () {
        response.headers.set(HttpHeaders.locationHeader,
            "http://127.0.0.1:${server.port}/301target");
        response.statusCode = HttpStatus.movedPermanently;
        response.close();
      });
    });
    addRequestHandler("/301target",
        (HttpRequest request, HttpResponse response) {
      Expect.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.equals("POST", request.method);
        response.headers.set(HttpHeaders.locationHeader,
            "http://127.0.0.1:${server.port}/303target");
        response.statusCode = HttpStatus.seeOther;
        response.close();
      });
    });
    addRequestHandler("/303target",
        (HttpRequest request, HttpResponse response) {
      Expect.equals("GET", request.method);
      response.close();
    });

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

    completer.complete(server);
  });
  return completer.future;
}

// A second HTTP server used to validate that redirect requests across domains
// do *not* include security-related headers.
Future<HttpServer> setupTargetServer() {
  final completer = new Completer<HttpServer>();
  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 (request.uri.path == "/target") {
        Expect.equals("value", request.headers.value("X-Request-Header"));
        Expect.isNull(request.headers.value("Authorization"),
            "expected 'Authorization' header to be removed on redirect");
        request.response.close();
      } else {
        request.listen((_) {}, onDone: () {
          request.response.statusCode = 404;
          request.response.close();
        });
      }
    });

    completer.complete(server);
  });
  return completer.future;
}

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

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

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

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

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

    int redirectCount = 0;

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

    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");
      request.headers.add("Authorization", "Basic ...");
      return request.close();
    }).then(handleResponse);
  });
}

void testAutoRedirect() {
  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((_) => Expect.fail("Response data not expected"),
          onDone: () {
        Expect.equals(1, response.redirects.length);
        server.close();
        client.close();
      });
    });
  });
}

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

    client
        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/redirect"))
        .then((HttpClientRequest request) {
      request
        ..followRedirects = true
        ..maxRedirects = 0;

      return request.close();
    }).then((HttpClientResponse response) {
      response.drain();
      Expect.fail("Response data not expected");
    }, onError: (error) {
      final httpException = error as HttpException;
      Expect.equals(httpException.message, "Redirect limit exceeded");
      Expect.equals(httpException.uri, null);
      server.close();
      client.close();
    });
  });
}

void testAutoRedirectWithHeaders() {
  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");
      request.headers.add("Authorization", "Basic ...");
      return request.close();
    }).then((HttpClientResponse response) {
      response.listen((_) => Expect.fail("Response data not expected"),
          onDone: () {
        Expect.equals(1, response.redirects.length);
        server.close();
        client.close();
      });
    });
  });
}

void testShouldCopyHeadersOnRedirect() {
  final clientClass = reflect(HttpClient()).type;
  final fnName = Symbol("shouldCopyHeaderOnRedirect");

  shouldCopyHeaderOnRedirect(
          String headerKey, Uri originalUrl, Uri redirectUri) =>
      clientClass.invoke(
          fnName, [headerKey, originalUrl, redirectUri]).reflectee as bool;

  checkShouldCopyHeader(
      String headerKey, String originalUrl, String redirectUri, bool expected) {
    if (shouldCopyHeaderOnRedirect(
            headerKey, Uri.parse(originalUrl), Uri.parse(redirectUri)) !=
        expected) {
      Expect.fail(
          "shouldCopyHeaderOnRedirect($headerKey, $originalUrl, $redirectUri) => ${!expected}");
    }
  }

  // Redirect on localhost.
  checkShouldCopyHeader(
      "authorization", "http://localhost", "http://localhost/foo", true);
  checkShouldCopyHeader(
      "cat", "http://localhost", "http://localhost/foo", true);

  // Redirect to same IP address.
  checkShouldCopyHeader("authorization", "http://192.168.20.20",
      "http://192.168.20.20/foo", true);
  checkShouldCopyHeader(
      "cat", "http://192.168.20.20", "http://192.168.20.20/foo", true);

  // Redirect to different IP address.
  checkShouldCopyHeader(
      "authorization", "http://192.168.20.20", "http://192.168.20.99", false);
  checkShouldCopyHeader(
      "cat", "http://192.168.20.20", "http://192.168.20.99", true);

  // Redirect to same domain.
  checkShouldCopyHeader(
      "authorization", "http://foo.com", "http://foo.com/foo", true);
  checkShouldCopyHeader("cat", "http://foo.com", "http://foo.com/foo", true);

  // Redirect to same domain with explicit ports.
  checkShouldCopyHeader(
      "authorization", "http://foo.com", "http://foo.com:80/foo", true);
  checkShouldCopyHeader("cat", "http://foo.com", "http://foo.com:80/foo", true);

  // Redirect to subdomain.
  checkShouldCopyHeader(
      "authorization", "https://foo.com", "https://www.foo.com", true);
  checkShouldCopyHeader("cat", "https://foo.com", "https://www.foo.com", true);

  // Redirect to different domain.
  checkShouldCopyHeader(
      "authorization", "https://foo.com", "https://wwwfoo.com", false);
  checkShouldCopyHeader("cat", "https://foo.com", "https://wwwfoo.com", true);

  // Redirect to different port.
  checkShouldCopyHeader(
      "authorization", "http://foo.com", "http://foo.com:81", false);
  checkShouldCopyHeader("cat", "http://foo.com", "http://foo.com:81", true);

  // Redirect from secure to insecure.
  checkShouldCopyHeader(
      "authorization", "https://foo.com", "http://foo.com", false);
  checkShouldCopyHeader("cat", "https://foo.com", "http://foo.com", true);

  // Redirect from secure to insecure, same port.
  checkShouldCopyHeader(
      "authorization", "https://foo.com:8888", "http://foo.com:8888", false);
  checkShouldCopyHeader(
      "cat", "https://foo.com:8888", "http://foo.com:8888", true);

  // Redirect from insecure to secure.
  checkShouldCopyHeader(
      "authorization", "http://foo.com", "https://foo.com", false);
  checkShouldCopyHeader("cat", "http://foo.com", "https://foo.com", true);

  // Redirect to subdomain, different port.
  checkShouldCopyHeader(
      "authorization", "https://foo.com:80", "https://www.foo.com:81", false);
  checkShouldCopyHeader(
      "cat", "https://foo.com:80", "https://www.foo.com:81", true);

  // Different header casting:
  checkShouldCopyHeader(
      "AuThOrIzAtiOn", "https://foo.com", "https://bar.com", false);
}

void testCrossDomainAutoRedirectWithHeaders() {
  setupTargetServer().then((targetServer) {
    setupServer(
            targetServer:
                Uri.parse("http://127.0.0.1:${targetServer.port}/target"))
        .then((server) {
      HttpClient client = new HttpClient();

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

void testAutoRedirect301POST() {
  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.equals(HttpStatus.movedPermanently, response.statusCode);
      response.listen((_) => Expect.fail("Response data not expected"),
          onDone: () {
        Expect.equals(0, response.redirects.length);
        server.close();
        client.close();
      });
    });
  });
}

void testAutoRedirect303POST() {
  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.equals(HttpStatus.ok, response.statusCode);
      response.listen((_) => Expect.fail("Response data not expected"),
          onDone: () {
        Expect.equals(1, response.redirects.length);
        server.close();
        client.close();
      });
    });
  });
}

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

    Future<HttpClientResponse?>.value(client
            .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
            .then((HttpClientRequest request) => request.close()))
        .catchError((error) {
      Expect.equals(5, error.redirects.length);
      server.close();
      client.close();
    }, test: (e) => e is RedirectException);
  });
}

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

    int redirectCount = 0;
    Future<HttpClientResponse?>.value(client
            .getUrl(Uri.parse("http://127.0.0.1:${server.port}/A"))
            .then((HttpClientRequest request) => request.close()))
        .catchError((error) {
      Expect.equals(2, error.redirects.length);
      server.close();
      client.close();
    }, test: (e) => e is RedirectException);
  });
}

void testRedirectClosingConnection() {
  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.equals(1, response.redirects.length);
        server.close();
        client.close();
      });
    });
  });
}

void testRedirectRelativeUrl() {
  testPath(String path) {
    setupServer().then((server) {
      HttpClient client = new HttpClient();

      print(path);
      client
          .getUrl(Uri.parse("http://127.0.0.1:${server.port}$path"))
          .then((request) => request.close())
          .then((response) {
        response.listen((_) {}, onDone: () {
          Expect.equals(HttpStatus.ok, response.statusCode);
          Expect.equals(1, response.redirects.length);
          server.close();
          client.close();
        });
      });
    });
  }

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

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

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

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

main() {
  testManualRedirect();
  testManualRedirectWithHeaders();
  testAutoRedirect();
  testAutoRedirectZeroMaxRedirects();
  testAutoRedirectWithHeaders();
  testShouldCopyHeadersOnRedirect();
  testCrossDomainAutoRedirectWithHeaders();
  testAutoRedirect301POST();
  testAutoRedirect303POST();
  testAutoRedirectLimit();
  testRedirectLoop();
  testRedirectClosingConnection();
  testRedirectRelativeUrl();
  testRedirectRelativeToAbsolute();
}
