繁体   English   中英

如何从 java.net.HttpClient 请求的响应中获取 http 状态消息

[英]How do I get the http status message from responses on java.net.HttpClient requests

一些 http 服务器会生成带有状态代码和自定义状态消息的响应。 当使用 java HttpURLConnection class 发出请求时,可以访问此消息。 但是,使用最近的java.net.HttpClient样式 api 我似乎无法找到访问消息本身的方法。 我只能找到一种获取状态码的方法。

  • 有没有办法检索我忽略的状态消息?
  • 如果无法获取状态消息,这是故意的吗?

为了说明这种情况,请考虑以下代码:

/**
 * Stand in replacement for a server which puts a custom message in the http status.
 * Blindly sends a fixed http response on every connection in receives, irrespective
 * of protocol or context.
 */
public class ExampleServer {

    private static final int port = 8080;
    private static final byte [] fixed_response = String.join ("\n",
        "HTTP/1.1 403 Missing X-Api-Key header",
        "Content-Length: 12",
        "",
        "Unauthorized"
    ).getBytes(StandardCharsets.UTF_8);

    public static void main (String [] args) throws Exception {
        ServerSocket server = new ServerSocket (port);
        ExecutorService executor = Executors.newCachedThreadPool ();
        while ( true ) {
            Socket socket = server.accept ();
            executor.submit (() -> {
                socket.getOutputStream ().write (fixed_response);
                socket.close ();
                return null;
            });
        }
    }

}

我们可以使用HttpURLConnection方法显示状态。

URI uri = URI.create ("http://localhost:" + port + "/any/path");
HttpURLConnection connection = (HttpURLConnection) uri.toURL ().openConnection ();
connection.setRequestMethod ("GET");

System.out.println ("status: " + connection.getResponseCode () + " " + connection.getResponseMessage ());
System.out.println ("body  : " + new String (connection.getErrorStream ().readAllBytes ()));

在以下场景中,我将如何创建相同的 output?

HttpClient client = HttpClient.newHttpClient ();
HttpRequest request = HttpRequest.newBuilder ()
    .uri (URI.create ("http://localhost:" + port + "/any/path"))
    .GET ().build ();
HttpResponse<String> response = client.send (request, HttpResponse.BodyHandlers.ofString ());

System.out.println ("status: " + response.statusCode () + " " /* what goes here? */);
System.out.println ("body  : " + response.body ());

“原因短语”真的无关紧要,在 HTTP/2 和 HTTP/3 中不再存在。 我不会在这方面付出太多努力。

正如 Julian 所说,这个原因在 HTTP/2 中不再存在。 虽然,如果您确实需要获取给定状态代码的名称,您可以使用Map将数字与名称匹配。

这是使用MDN名称的代码的 Map 代码。

import java.util.Map;

import static java.util.Map.entry;

public class HttpStatusReasons {

    private static final String UNKNOWN_STATUS = "Unknown Status";

    private static final Map<Integer, String> REASONS = Map.ofEntries(
            // informational
            entry(100, "Continue"),
            entry(101, "Switching Protocol"),
            entry(102, "Processing"),
            entry(103, "Early Hints"),

            // successful
            entry(200, "OK"),
            entry(201, "Created"),
            entry(202, "Accepted"),
            entry(203, "Non-Authoritative Information"),
            entry(204, "No Content"),
            entry(205, "Reset Content"),
            entry(206, "Partial Content"),
            entry(207, "Multi Status"),
            entry(208, "Already Reported"),
            entry(226, "IM Used"),

            // redirection
            entry(300, "Multiple Choice"),
            entry(301, "Moved Permanently"),
            entry(302, "Found"),
            entry(303, "See Other"),
            entry(304, "Not Modified"),
            entry(305, "Use Proxy"), // deprecated
            entry(307, "Temporary Redirect"),
            entry(308, "Permanent Redirect"),

            // client error
            entry(400, "Bad Request"),
            entry(401, "Unauthorized"),
            entry(402, "Payment Required"),
            entry(403, "Forbidden"),
            entry(404, "Not Found"),
            entry(405, "Method Not Allowed"),
            entry(406, "Not Acceptable"),
            entry(407, "Proxy Authentication Required"),
            entry(408, "Request Timeout"),
            entry(409, "Conflict"),
            entry(410, "Gone"),
            entry(411, "Length Required"),
            entry(412, "Precondition Failed"),
            entry(413, "Payload Too Long"),
            entry(414, "URI Too Long"),
            entry(415, "Unsupported Media Type"),
            entry(416, "Range Not Satisfiable"),
            entry(417, "Expectation Failed"),
            entry(418, "I'm a Teapot"),
            entry(421, "Misdirected Request"),
            entry(422, "Unprocessable Entity"),
            entry(423, "Locked"),
            entry(424, "Failed Dependency"),
            entry(425, "Too Early"),
            entry(426, "Upgrade Required"),
            entry(428, "Precondition Required"),
            entry(429, "Too Many Requests"),
            entry(431, "Request Header Fields Too Large"),
            entry(451, "Unavailable for Legal Reasons"),

            // server error
            entry(500, "Internal Server Error"),
            entry(501, "Not Implemented"),
            entry(502, "Bad Gateway"),
            entry(503, "Service Unavailable"),
            entry(504, "Gateway Timeout"),
            entry(505, "HTTP Version Not Supported"),
            entry(506, "Variant Also Negotiates"),
            entry(507, "Insufficient Storage"),
            entry(508, "Loop Detected"),
            entry(510, "Not Extended"),
            entry(511, "Network Authentication Required")
    );

    public static String getReasonForStatus(int status) {
        return REASONS.getOrDefault(status, UNKNOWN_STATUS);
    }
}

如果您使用 spring ,您可以使用来自 org.springframework.http.HttpStatus 的 HttpStatus ,如下所示:

HttpStatus.valueOf(connection.getResponseCode()).getReasonPhrase()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM