1

With Java's java.net.HttpURLConnection there is a getResponseMessage() method to retrieve any Reason-Phrase text (as specified by RFC2616 6.1 Status Line).

In the newer Java 11 HttpClient, java.net.http.HttpResponse only has a statusCode() method.

Is there a way to obtain text returned on the end of the status line using this API? If not, why was it not included? (I know that HTTP 2 does not define this value, but most applications still use HTTP 1.1 where it remains valid.)

Nathan Williams
  • 892
  • 9
  • 10

3 Answers3

2

Is there a way to obtain text returned on the end of the status line using this API?

No.

If not, why was it not included?

  1. Because the text is routinely ignored by clients. (Bear with me ...)

  2. Because the text rarely contains anything useful. It is usually just the standard (recommended) text message corresponding to the response code. (This is one reason why the text is routinely ignored by clients.)

  3. Because if a web application is going to provide a meaningful explanation, it is likely to do it in the payload. (Because of 1. But also reinforcing it.)

  4. Because some web stacks don't let the web app set the reason text.

  5. Because some HTTP 1.1 web servers routinely leave the reason text out entirely! (For example, with Tomcat 8.0.x there is no message, and with Tomcat 8.5.x there is an option to enable it.)


(I know that HTTP 2 does not define this value, but most applications still use HTTP 1.1 where it remains valid.)

That's now ...

This is actually another reason for (new) web applications not try to pass useful information in the reason text AND to not support it in the API.

Eventually, most applications will use HTTP 2 or later. Or at least, enough will use it that relying on good support for an HTTP 1.x feature could cause problems for your application.

Bear in mind that HTTP 3 is now in the pipeline. Nobody can see far enough into the future to accurately predict what proportion of web servers will use what versions of HTTP in (say) 5 years time.


In the light of the above, if you make your client code depend on seeing specific reason texts ... or seeing any at all ... then it is liable to break for some web servers.

Hence, I would say that Java 11's HttpClient API designers did us all a big favor by not exposing the reason text to client-side code.

You are free to disagree ... and use other HTTP client libraries.


My advice is to go with the flow. If you don't try to use the reason text (client side or server side) then you won't have to deal with the problems that using it will bring. The problems will only get worse.

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
  • All good reasons that probably explain the decision. It’s still unfortunate that spec support is selective for something that was previously included. Now that Java is moving faster and communicating deprecation better, this would have been easy to include to smooth migration and later remove when/if usage abated. I guess it’s hard to assess...there are a lot of private services out there. – Nathan Williams Aug 26 '20 at 17:13
  • *"It’s still unfortunate that spec support is selective for something that was previously included."* - Matter of opinion. I would say it is a good thing. *"Now that Java is moving faster and communicating deprecation better, this would have been easy to include to smooth migration and later remove when/if usage abated. I guess it’s hard to assess...there are a lot of private services out there."* - We are talking about a brand new API. The old Java SE APIs continue to exist, and AFAIK there has been no talk of deprecation. – Stephen C Aug 27 '20 at 00:09
  • People who are using the older APIs and are making (non-trivial) use of the reason text are going to be stuck on HTTP 1.x. It doesn't look like `HttpUrlConnection` etc are likely to be to support HTTP 2. Take a read of [JEP 110](https://openjdk.java.net/jeps/110). My take is that they are viewing `HttpUrlConnection` as legacy ... like the old Java date / time stuff and `java.io.File`. – Stephen C Aug 27 '20 at 00:23
0

As you noticed the HttpResponse doesn't provide any API to get the reason phrase. There is no hidden way to get it. Do you have a use case where having an accessor for the reason phrase in HttpResponse would be useful?

daniel
  • 1,504
  • 2
  • 12
  • Most typically as a simple way to communicate error text that expands on the status code. It’s more work to negotiate a payload format for a short message than to just use a slot the spec itself provides. – Nathan Williams Aug 26 '20 at 17:03
  • You could possibly use an immutable static hashmap (or switch statement) to map the status code to its standard reason phrase. – daniel Aug 27 '20 at 09:24
  • The point is that a server may express unique detail in the reason phrase that a canned mapping would not reflect. ex: https://stackoverflow.com/a/6123801/1723949 That’s a pattern that’s going to decline with HTTP 2 adoption, but it’s still in use today. – Nathan Williams Aug 27 '20 at 13:21
  • Well - have you encountered this often? I would expect the response body to contain the details. – daniel Aug 27 '20 at 19:39
  • I’ve used it in simple services. There’s no way of knowing how common it is in the wild. It remains part of the servlet spec, so there is some asymmetry in the client API decision (though this stuff is less monolithic than it used to be). – Nathan Williams Aug 27 '20 at 22:35
0

I was looking for http status code reason phrases in Java and found this discussion during my Google search. I ended up writing my own function that I wanted to share in case somebody else finds it useful. It might not be complete, but it serves my purposes.

public static String getReasonPhrase(int statusCode) {
    switch(statusCode) {
        case (200): return "OK";
        case (201): return "Created";
        case (202): return "Accepted";
        case (203): return "Non Authoritative Information";
        case (204): return "No Content";
        case (205): return "Reset Content";
        case (206): return "Partial Content";
        case (207): return "Partial Update OK";
        case (300): return "Mutliple Choices";
        case (301): return "Moved Permanently";
        case (302): return "Moved Temporarily";
        case (303): return "See Other";
        case (304): return "Not Modified";
        case (305): return "Use Proxy";
        case (307): return "Temporary Redirect";
        case (400): return "Bad Request";
        case (401): return "Unauthorized";
        case (402): return "Payment Required";
        case (403): return "Forbidden";
        case (404): return "Not Found";
        case (405): return "Method Not Allowed";
        case (406): return "Not Acceptable";
        case (407): return "Proxy Authentication Required";
        case (408): return "Request Timeout";
        case (409): return "Conflict";
        case (410): return "Gone";
        case (411): return "Length Required";
        case (412): return "Precondition Failed";
        case (413): return "Request Entity Too Large";
        case (414): return "Request-URI Too Long";
        case (415): return "Unsupported Media Type";
        case (416): return "Requested Range Not Satisfiable";
        case (417): return "Expectation Failed";
        case (418): return "Reauthentication Required";
        case (419): return "Proxy Reauthentication Required";
        case (422): return "Unprocessable Entity";
        case (423): return "Locked";
        case (424): return "Failed Dependency";
        case (500): return "Server Error";
        case (501): return "Not Implemented";
        case (502): return "Bad Gateway";
        case (503): return "Service Unavailable";
        case (504): return "Gateway Timeout";
        case (505): return "HTTP Version Not Supported";
        case (507): return "Insufficient Storage";
        default: return "";
    }
}
Bjorn
  • 1