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

/// @assertion bool followRedirects
///  read / write
/// Set this property to true if this request should automatically follow
/// redirects. The default is true.
///
/// Automatic redirect will only happen for "GET" and "HEAD" requests and only
/// for the status codes HttpHeaders.MOVED_PERMANENTLY (301), HttpStatus.found
/// (302), HttpStatus.movedTemporarily (302, alias for HttpStatus.found),
/// HttpStatus.seeOther (303) and HttpStatus.temporaryRedirect (307). For
/// HttpStatus.seeOther (303) automatic redirect will also happen for "POST"
/// requests with the method changed to "GET" when following the redirect.
///
/// All headers added to the request will be added to the redirection request(s).
/// However, any body send with the request will not be part of the redirection
/// request(s).
/// @description Checks that redirect doesn't happen for DELETE, PUT, POST and
/// PATCH requests
/// @author sgrekhov@unipro.ru

import "dart:io";
import "dart:async";
import "dart:convert";
import "../../../Utils/expect.dart";

var localhost = InternetAddress.loopbackIPv4.address;

test(String method, int statusCode) async {
  asyncStart();
  HttpServer server = await HttpServer.bind(localhost, 0);
  int counter = 0;
  Uri redirectUri = Uri.parse("http://${localhost}:${server.port}/yyy");
  server.listen((HttpRequest request) {
    if (counter == 0) {
      new Future.delayed(new Duration(seconds: 1), () {
        server.close();
        asyncEnd();
      });
    }
    if (request.uri.path == "/xxx") {
        if (counter++ > 0) {
          Expect.fail("Excessive request");
        }
        request.response.redirect(redirectUri, status: statusCode);
    } else {
      Expect.fail("Wrong URI:" + request.uri.path);
    }
  });

  HttpClient client = new HttpClient();
  client.open(method, localhost, server.port, "/xxx")
      .then((HttpClientRequest request) {
        return request.close();
  }).then((HttpClientResponse response) {
    response.cast<List<int>>().transform(utf8.decoder).listen((content) {});
  });
}

main() {
  test("DELETE", HttpStatus.movedPermanently);
  test("DELETE", HttpStatus.found);
  test("DELETE", HttpStatus.movedTemporarily);
  test("DELETE", HttpStatus.seeOther);
  test("DELETE", HttpStatus.temporaryRedirect);
  test("DELETE", HttpStatus.permanentRedirect);

  test("PUT", HttpStatus.movedPermanently);
  test("PUT", HttpStatus.found);
  test("PUT", HttpStatus.movedTemporarily);
  test("PUT", HttpStatus.seeOther);
  test("PUT", HttpStatus.temporaryRedirect);
  test("PUT", HttpStatus.permanentRedirect);

  test("POST", HttpStatus.movedPermanently);
  test("POST", HttpStatus.found);
  test("POST", HttpStatus.movedTemporarily);
  test("POST", HttpStatus.temporaryRedirect);
  test("POST", HttpStatus.permanentRedirect);

  test("PATCH", HttpStatus.movedPermanently);
  test("PATCH", HttpStatus.found);
  test("PATCH", HttpStatus.movedTemporarily);
  test("PATCH", HttpStatus.seeOther);
  test("PATCH", HttpStatus.temporaryRedirect);
  test("PATCH", HttpStatus.permanentRedirect);
}
