在 Java 11 及更高版本中使用 HttpClient 时如何跟踪 HTTP 303 状态代码?

How to follow-through on HTTP 303 status code when using HttpClient in Java 11 and later?

当使用 java.net.http.HttpClient classes in Java 11 and later, how does one tell the client to follow through an HTTP 303 到达重定向页面时?

这是一个例子。 Wikipedia provides a REST URL 用于获取其内容的随机页面的摘要。 URL 重定向到随机选择页面的 URL。当 运行ning 这段代码时,我在调用 HttpResponse#toString 时看到了 303。但我不知道如何告诉客户 class 跟随新的 URL。

HttpClient client = HttpClient.newHttpClient();
HttpRequest request =
        HttpRequest
                .newBuilder()
                .uri( URI.create( "https://en.wikipedia.org/api/rest_v1/page/random/summary" ) )
                .build();
try
{
    HttpResponse < String > response = client.send( request , HttpResponse.BodyHandlers.ofString() );
    System.out.println( "response = " + response );   // ⬅️ We can see the `303` status code.
    String body = response.body();
    System.out.println( "body = " + body );
}
catch ( IOException e )
{
    e.printStackTrace();
}
catch ( InterruptedException e )
{
    e.printStackTrace();
}

当运行:

response = (GET https://en.wikipedia.org/api/rest_v1/page/random/summary) 303

body =

问题

您正在使用 HttpClient#newHttpClient()。该方法的文档指出:

Returns a new HttpClient with default settings.

Equivalent to newBuilder().build().

The default settings include: the "GET" request method, a preference of HTTP/2, a redirection policy of NEVER [emphasis added], the default proxy selector, and the default SSL context.

正如所强调的,您正在创建一个重定向策略为 NEVERHttpClient


解决方案

您的问题至少有两种解决方案。

自动跟随重定向

如果你想自动遵循重定向,那么你需要在构建客户端之前使用HttpClient#newBuilder() (instead of #newHttpClient()) which allows you to configure the to-be-built client. Specifically, you need to call HttpClient.Builder#followRedirects(HttpClient.Redirect)和适当的重定向策略。例如:

HttpClient client = 
    HttpClient.newBuilder()
        .followRedirects(HttpClient.Redirect.NORMAL) // follow redirects
        .build();

不同的重定向策略由 HttpClient.Redirect 枚举指定:

Defines the automatic redirection policy.

The automatic redirection policy is checked whenever a 3XX response code is received. If redirection does not happen automatically, then the response, containing the 3XX response code, is returned, where it can be handled manually.

共有三个常量:ALWAYSNEVERNORMAL。前两者的含义从他们的名字就可以看出。最后一个 NORMAL 的行为与 ALWAYS 类似,只是它不会从 https URL 重定向到 http URL。

手动关注重定向

HttpClient.Redirect 的文档中所述,您可以改为手动跟随重定向。我不太精通 HTTP 以及如何正确处理所有响应,因此我不会在这里举一个例子。但我相信,至少,这需要你:

  1. 检查响应的状态码。
  2. 如果代码指示重定向,请从 response headers 中获取新的 URI。
  3. 如果新 URI 是相对的,则根据请求 URI 解析它。
  4. 发送新请求。
  5. 根据需要重复 1-4。

显然,将 HttpClient 配置为自动跟随重定向要容易得多(并且不易出错),但这种方法会给您更多的控制权。