Zoltan Szilagyi
Zoltan Szilagyi

Reputation: 3538

Does Java have a complete enum for HTTP response codes?

I'm wondering if there is an enum type in some standard Java class library that defines symbolic constants for all of the valid HTTP response codes. It should support conversion to/from the corresponding integer values.

I'm debugging some Java code that uses javax.ws.rs.core.Response.Status. It works, but it only defines about half of the valid HTTP response codes.

Upvotes: 338

Views: 261818

Answers (17)

John Feminella
John Feminella

Reputation: 311436

I don't think there's one that's complete in the standard Java classes; HttpURLConnection is missing quite a few codes, like HTTP 100/Continue.

There's a complete list in the Apache HttpComponents, though:
org.apache.http.HttpStatus (replaced org.apache.commons.HttpClient.HttpStatus from Apache Http Client, which reached end of life)

Upvotes: 351

David Tonhofer
David Tonhofer

Reputation: 15316

Java still doesn't have it?

Oh well! Here's a quasi-enum. Remove the NotNull/Nullable references if so desired or replace their imports according to taste.

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

// ---
// From https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
//
// You can write code like this:
//
/*
final var x = HttpStatusCode.fromCode(203);
        System.out.println(x); // "203"
        System.out.println(x.toStringWithText()); // "203 Non Authoritative Information"

final var y = HttpStatusCode.fromText("Non Authoritative Information").orElseThrow();
        System.out.println(y); // "203"
        System.out.println(y.toStringWithText()); // "203 Non Authoritative Information"

final var z = HttpStatusCode.fromText("Internal Server Error").orElseThrow();
        System.out.println(z); // "500"
        System.out.println(z.toStringWithText()); // "500 Internal Server Error"

        assert x.equals(HttpStatusCode.fromText("Non Authoritative Information").orElseThrow());
        assert x == HttpStatusCode.fromText("Non Authoritative Information").orElseThrow();
        assert x.equals(y);
        assert x == y;
        assert !x.equals(z);
        assert x != z;
 */
// ---

public final class HttpStatusCode {

    private static Map<Integer, String> codeToTextMap;
    private static Map<Integer, String> codeToTextMapUnofficials;
    private static Map<String, Integer> textToCodeMap;

    // This map grows as we request new instances via valueOf().
    // Access to it is synchronized in valueOf().

    private final static Map<Integer, HttpStatusCode> canonicals = new HashMap<>();

    static {
        Map<Integer, String> map = new HashMap<>();
        map.put(100, "Continue");
        map.put(101, "Switching Protocols");
        map.put(102, "Processing");
        map.put(103, "Early Hints");
        map.put(200, "OK");
        map.put(201, "Created");
        map.put(202, "Accepted");
        map.put(203, "Non Authoritative Information");
        map.put(204, "No Content");
        map.put(205, "Reset Content");
        map.put(206, "Partial Content");
        map.put(207, "Multi-Status");
        map.put(208, "Already Reported");
        map.put(226, "IM Used");
        map.put(300, "Multiple Choices");
        map.put(301, "Moved Permanently");
        map.put(302, "Found");
        map.put(303, "See Other");
        map.put(304, "Not Modified");
        map.put(305, "Use Proxy");
        map.put(307, "Temporary Redirect");
        map.put(308, "Permanent Redirect");
        map.put(400, "Bad Request");
        map.put(401, "Unauthorized");
        map.put(402, "Payment Required");
        map.put(403, "Forbidden");
        map.put(404, "Not Found");
        map.put(405, "Method Not Allowed");
        map.put(406, "Not Acceptable");
        map.put(407, "Proxy Authentication Required");
        map.put(408, "Request Timeout");
        map.put(409, "Conflict");
        map.put(410, "Gone");
        map.put(411, "Length Required");
        map.put(412, "Precondition Failed");
        map.put(413, "Payload Too Large");
        map.put(414, "URI Too Long");
        map.put(415, "Unsupported Media Type");
        map.put(416, "Range Not Satisfiable");
        map.put(417, "Expectation Failed");
        map.put(418, "I'm a teapot");
        map.put(421, "Misdirected Request");
        map.put(422, "Unprocessable Content");
        map.put(423, "Locked");
        map.put(424, "Failed Dependency");
        map.put(426, "Upgrade Required");
        map.put(428, "Precondition Required");
        map.put(429, "Too Many Requests");
        map.put(431, "Request Header Fields Too Large");
        map.put(451, "Unavailable For Legal Reasons");
        map.put(500, "Internal Server Error");
        map.put(501, "Not Implemented");
        map.put(502, "Bad Gateway");
        map.put(503, "Service Unavailable");
        map.put(504, "Gateway Timeout");
        map.put(505, "Http Version Not Supported");
        map.put(506, "Variant Also Negotiates");
        map.put(507, "Insufficient Storage");
        map.put(508, "Loop Detected");
        map.put(510, "Not Extended");
        map.put(511, "Network Authentication Required");
        HttpStatusCode.codeToTextMap = Collections.unmodifiableMap(map);
    }

    static {
        Map<Integer, String> map = new HashMap<>();
        map.put(218, "This is fine (Apache HTTP Server)");
        map.put(419, "Page Expired (Laravel Framework)");
        map.put(420, "Method Failure (Spring Framework), Enhance Your Calm (Twitter)");
        map.put(430, "Shopify Security Rejection (Shopify)");
        map.put(450, "Blocked by Windows Parental Controls (Microsoft)");
        map.put(498, "Invalid Token (Esri)");
        map.put(499, "Token Required (Esri)");
        map.put(509, "Bandwidth Limit Exceeded (Apache Web Server/cPanel)");
        map.put(529, "Site is overloaded (Qualys)");
        map.put(530, "Site is frozen (Pantheon), Origin DNS Error (Shopify)");
        map.put(540, "Temporarily Disabled (Shopify)");
        map.put(598, "Network read timeout error (Informal convention)");
        map.put(599, "Network Connect Timeout Error (Inofficial)");
        map.put(783, "Unexpected Token (Shopify)");
        HttpStatusCode.codeToTextMapUnofficials = Collections.unmodifiableMap(map);
    }

    static {
        // Note that we don't put the "unofficials" into the reverse map
        Map<String, Integer> reverseMap = new HashMap<>();
        HttpStatusCode.codeToTextMap.forEach((key, value) -> {
            var old = reverseMap.put(value.toLowerCase().replace(" ", ""), key);
            assert old == null;
        });
        HttpStatusCode.textToCodeMap = Collections.unmodifiableMap(reverseMap);
    }

    // ---
    // Some often used codes that you will use directly
    // ---

    public final static HttpStatusCode ok = fromCode(200);
    public final static HttpStatusCode unauthorized = fromCode(401);
    public final static HttpStatusCode forbidden = fromCode(403);
    public final static HttpStatusCode missing = fromCode(404);
    public final static HttpStatusCode moved = fromCode(301);
    public final static HttpStatusCode internal_server_error = fromCode(500);

    private final int code;
    private final int hashCode;
    private final String asString;
    private final String asStringWithText;

    // ---
    // Constructor is private because customers are expected to only call fromCode() and fromText().
    // ---

    private HttpStatusCode(int code) {
        if (code < 100 || code > 999) {
            throw new IllegalArgumentException("Code " + code + " is out of range [100,999]");
        }
        this.code = code;
        this.hashCode = Objects.hashCode(code);
        this.asString = String.valueOf(code);
        if (codeToTextMap.containsKey(code)) {
            this.asStringWithText = code + " " + codeToTextMap.get(code);
        } else if (codeToTextMapUnofficials.containsKey(code)) {
            this.asStringWithText = code + " " + codeToTextMapUnofficials.get(code);
        } else {
            this.asStringWithText = asString;
        }
    }

    // ---
    // Is there a text description for this instance?
    // ---

    public boolean existsText() {
        return codeToTextMap.containsKey(code) || codeToTextMapUnofficials.containsKey(code);
    }

    // ---
    // No surprises hash code based on the HTTP status code
    // ---

    @Override
    public int hashCode() {
        return hashCode;
    }

    // ---
    // toString() just returns the string-ified numeric code
    // ---

    @Override
    public @NotNull String toString() {
        return asString;
    }

    // ---
    // Equality is basically on code
    // ---

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            assert this.code == ((HttpStatusCode) obj).code;
            return true;
        } else {
            assert !(obj instanceof HttpStatusCode) || this.code != ((HttpStatusCode) obj).code;
            return false;
        }
    }

    // ---
    // Returns the string-ified numeric code and any existing text description that is associated to it
    // ---

    public @NotNull String toStringWithText() {
        return asStringWithText;
    }

    // ---
    // Try to find an official code (the unofficial code are disregarded)
    // that corresponds to the passed "desc" (the description in english)
    // Casing is disregarded, as are blanks.

    public static Optional<HttpStatusCode> fromText(@Nullable String desc) {
        if (desc == null) {
            return Optional.empty();
        } else {
            final String lookFor = desc.toLowerCase().replace(" ", "");
            final Integer res = textToCodeMap.get(lookFor);
            if (res == null) {
                return Optional.empty();
            } else {
                return Optional.of(fromCode(res)); // a new instance may be created
            }
        }
    }

    // ---
    // Obtain a canonical instance of HttpStatusCode.
    // If none exists for that code, it is created.
    // ---

    public static @NotNull HttpStatusCode fromCode(int code) {
        synchronized (canonicals) {
            final HttpStatusCode res = canonicals.get(code);
            if (res != null) {
                return res;
            } else {
                final HttpStatusCode res2 = new HttpStatusCode(code);
                canonicals.put(code, res2);
                return res2;
            }
        }
    }
}

Upvotes: 0

Steffi Keran Rani J
Steffi Keran Rani J

Reputation: 4093

You can use HttpStatusCode from AWS if you are developing for AWS services.

Just import software.amazon.awssdk.http.HttpStatusCode;

It has enum for all status codes:

eg.

HttpStatusCode.INTERNAL_SERVER_ERROR for 500

HttpStatusCode.OK for 200

Upvotes: 0

Dorad
Dorad

Reputation: 3713

Yet another library to the list:

org.glassfish.grizzly.http.util.HttpStatus

public static final HttpStatus CONINTUE_100 = register(100, "Continue");
public static final HttpStatus SWITCHING_PROTOCOLS_101 = register(101, "Switching Protocols");
public static final HttpStatus WEB_SOCKET_PROTOCOL_HANDSHAKE_101 = register(101, "Web Socket Protocol Handshake");
public static final HttpStatus OK_200 = register(200, "OK");
public static final HttpStatus CREATED_201 = register(201, "Created");
public static final HttpStatus ACCEPTED_202 = register(202, "Accepted");
public static final HttpStatus NON_AUTHORATIVE_INFORMATION_203 = register(203, "Not-Authoritative Information");
public static final HttpStatus NO_CONTENT_204 = register(204, "No Content");
public static final HttpStatus RESET_CONTENT_205 = register(205, "Reset Content");
public static final HttpStatus PARTIAL_CONTENT_206 = register(206, "Partial Content");
public static final HttpStatus MULTIPLE_CHOICES_300 = register(300, "Multiple Choices");
public static final HttpStatus MOVED_PERMANENTLY_301 = register(301, "Moved Permanently");
public static final HttpStatus FOUND_302 = register(302, "Found");
public static final HttpStatus SEE_OTHER_303 = register(303, "See Other");
public static final HttpStatus NOT_MODIFIED_304 = register(304, "Not Modified");
public static final HttpStatus USE_PROXY_305 = register(305, "Use Proxy");
public static final HttpStatus TEMPORARY_REDIRECT_307 = register(307, "Temporary Redirect");
public static final HttpStatus PERMANENT_REDIRECT_308 = register(308, "Permanent Redirect");
public static final HttpStatus BAD_REQUEST_400 = register(400, "Bad Request");
public static final HttpStatus UNAUTHORIZED_401 = register(401, "Unauthorized");
public static final HttpStatus PAYMENT_REQUIRED_402 = register(402, "Payment Required");
public static final HttpStatus FORBIDDEN_403 = register(403, "Forbidden");
public static final HttpStatus NOT_FOUND_404 = register(404, "Not Found");
public static final HttpStatus METHOD_NOT_ALLOWED_405 = register(405, "Method Not Allowed");
public static final HttpStatus NOT_ACCEPTABLE_406 = register(406, "Not Acceptable");
public static final HttpStatus PROXY_AUTHENTICATION_REQUIRED_407 = register(407, "Proxy Authentication Required");
public static final HttpStatus REQUEST_TIMEOUT_408 = register(408, "Request Timeout");
public static final HttpStatus CONFLICT_409 = register(409, "Conflict");
public static final HttpStatus GONE_410 = register(410, "Gone");
public static final HttpStatus LENGTH_REQUIRED_411 = register(411, "Length Required");
public static final HttpStatus PRECONDITION_FAILED_412 = register(412, "Precondition Failed");
public static final HttpStatus REQUEST_ENTITY_TOO_LARGE_413 = register(413, "Request Entity Too Large");
public static final HttpStatus REQUEST_URI_TOO_LONG_414 = register(414, "Request-URI Too Long");
public static final HttpStatus UNSUPPORTED_MEDIA_TYPE_415 = register(415, "Unsupported Media Type");
public static final HttpStatus REQUEST_RANGE_NOT_SATISFIABLE_416 = register(416, "Request Range Not Satisfiable");
public static final HttpStatus EXPECTATION_FAILED_417 = register(417, "Expectation Failed");
public static final HttpStatus MISDIRECTED_REQUEST = register(421, "Misdirected Request");
public static final HttpStatus REQUEST_HEADER_FIELDS_TOO_LARGE = register(431, "Request Header Fields Too Large");
public static final HttpStatus INTERNAL_SERVER_ERROR_500 = register(500, "Internal Server Error");
public static final HttpStatus NOT_IMPLEMENTED_501 = register(501, "Not Implemented");
public static final HttpStatus BAD_GATEWAY_502 = register(502, "Bad Gateway");
public static final HttpStatus SERVICE_UNAVAILABLE_503 = register(503, "Service Unavailable");
public static final HttpStatus GATEWAY_TIMEOUT_504 = register(504, "Gateway Timeout");
public static final HttpStatus HTTP_VERSION_NOT_SUPPORTED_505 = register(505, "HTTP Version Not Supported");

Upvotes: 0

Minh Chien
Minh Chien

Reputation: 1

pls try HttpStatus.ACCEPTED.value()

Upvotes: 0

Ye Gaung
Ye Gaung

Reputation: 11

Please see the following enum from the Spring framework which provides all the HTTP response status code

HttpStatus.values()

Upvotes: 1

Christian S.
Christian S.

Reputation: 982

Here's an enum with status codes and their descriptions that (at time of writing) corresponds to the HTTP status code registry.

Note that the registry might get updated, and that sometimes unofficial status codes are used.

public enum HttpStatusCode {

    //1xx: Informational
    CONTINUE(100, "Continue"),
    SWITCHING_PROTOCOLS(101, "Switching Protocols"),
    PROCESSING(102, "Processing"),
    EARLY_HINTS(103, "Early Hints"),

    //2xx: Success
    OK(200, "OK"),
    CREATED(201, "Created"),
    ACCEPTED(202, "Accepted"),
    NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
    NO_CONTENT(204, "No Content"),
    RESET_CONTENT(205, "Reset Content"),
    PARTIAL_CONTENT(206, "Partial Content"),
    MULTI_STATUS(207, "Multi-Status"),
    ALREADY_REPORTED(208, "Already Reported"),
    IM_USED(226, "IM Used"),

    //3xx: Redirection
    MULTIPLE_CHOICES(300, "Multiple Choice"),
    MOVED_PERMANENTLY(301, "Moved Permanently"),
    FOUND(302, "Found"),
    SEE_OTHER(303, "See Other"),
    NOT_MODIFIED(304, "Not Modified"),
    USE_PROXY(305, "Use Proxy"),
    TEMPORARY_REDIRECT(307, "Temporary Redirect"),
    PERMANENT_REDIRECT(308, "Permanent Redirect"),

    //4xx: Client Error
    BAD_REQUEST(400, "Bad Request"),
    UNAUTHORIZED(401, "Unauthorized"),
    PAYMENT_REQUIRED(402, "Payment Required"),
    FORBIDDEN(403, "Forbidden"),
    NOT_FOUND(404, "Not Found"),
    METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
    NOT_ACCEPTABLE(406, "Not Acceptable"),
    PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"),
    REQUEST_TIMEOUT(408, "Request Timeout"),
    CONFLICT(409, "Conflict"),
    GONE(410, "Gone"),
    LENGTH_REQUIRED(411, "Length Required"),
    PRECONDITION_FAILED(412, "Precondition Failed"),
    REQUEST_TOO_LONG(413, "Payload Too Large"),
    REQUEST_URI_TOO_LONG(414, "URI Too Long"),
    UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
    REQUESTED_RANGE_NOT_SATISFIABLE(416, "Range Not Satisfiable"),
    EXPECTATION_FAILED(417, "Expectation Failed"),
    MISDIRECTED_REQUEST(421, "Misdirected Request"),
    UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),
    LOCKED(423, "Locked"),
    FAILED_DEPENDENCY(424, "Failed Dependency"),
    TOO_EARLY(425, "Too Early"),
    UPGRADE_REQUIRED(426, "Upgrade Required"),
    PRECONDITION_REQUIRED(428, "Precondition Required"),
    TOO_MANY_REQUESTS(429, "Too Many Requests"),
    REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),
    UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"),

    //5xx: Server Error
    INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
    NOT_IMPLEMENTED(501, "Not Implemented"),
    BAD_GATEWAY(502, "Bad Gateway"),
    SERVICE_UNAVAILABLE(503, "Service Unavailable"),
    GATEWAY_TIMEOUT(504, "Gateway Timeout"),
    HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported"),
    VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"),
    INSUFFICIENT_STORAGE(507, "Insufficient Storage"),
    LOOP_DETECTED(508, "Loop Detected"),
    NOT_EXTENDED(510, "Not Extended"),
    NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required");

    private final int value;
    private final String description;

    HttpStatusCode(int value, String description) {
        this.value = value;
        this.description = description;
    }

    public int getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }

    @Override
    public String toString() {
        return value + " " + description;
    }

    public static HttpStatusCode getByValue(int value) {
        for(HttpStatusCode status : values()) {
            if(status.value == value) return status;
        }
        throw new IllegalArgumentException("Invalid status code: " + value);
    }
}

Upvotes: 16

David Rabinowitz
David Rabinowitz

Reputation: 30448

The Interface javax.servlet.http.HttpServletResponse from the servlet API has all the response codes in the form of int constants names SC_<description>. See http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html

Upvotes: 84

Maira Bay
Maira Bay

Reputation: 300

1) To get the reason text if you only have the code, you can use:

org.apache.http.impl.EnglishReasonPhraseCatalog.INSTANCE.getReason(httpCode,null)

Where httpCode would be the reason code that you got from the HTTP response.

See https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/impl/EnglishReasonPhraseCatalog.html for details

2) To get the reason code if you only have the text, you can use BasicHttpResponse.

See here for details: https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/message/BasicHttpResponse.html

Upvotes: 5

David Avendasora
David Avendasora

Reputation: 4558

Everyone seems to be ignoring the "enum type" portion of your question.

While there is no canonical source for HTTP Status Codes there is an simple way to add any missing Status constants you need to those provided by javax.ws.rs.core.Response.Status without adding any additional dependencies to your project.

javax.ws.rs.core.Response.Status is just one implementation of the javax.ws.rs.core.Response.StatusType interface. You simply need to create your own implementation enum with definitions for the Status Codes that you want.

Core libraries like Javax, Jersey, etc. are written to the interface StatusType not the implementation Status (or they certainly should be). Since your new Status enum implements StatusType it can be used anyplace you would use a javax.ws.rs.core.Response.Status constant.

Just remember that your own code should also be written to the StatusType interface. This will enable you to use both your own Status Codes along side the "standard" ones.

Here's a gist with a simple implementation with constants defined for the "Informational 1xx" Status Codes: https://gist.github.com/avendasora/a5ed9acf6b1ee709a14a

Upvotes: 12

Andrejs
Andrejs

Reputation: 27677

If you are using Netty, you can use:

Upvotes: 7

ak123
ak123

Reputation: 295

Another option is to use HttpStatus class from the Apache commons-httpclient which provides you the various Http statuses as constants.

Upvotes: -1

user1050755
user1050755

Reputation: 11691

The best provider for http status code constants is likely to be Jetty's org.eclipse.jetty.http.HttpStatus class because:

  • there is a javadoc package in maven which is important if you search for the constant and only know the number -> just open the api docs page and search for the number
  • the constants contain the status code number itself.

Only thing I would improve: put the status code number in front of the text description in order to make auto-completion lookup more convient when you are starting with the code.

Upvotes: 1

Andr&#233;s Canavesi
Andr&#233;s Canavesi

Reputation: 2174

Use javax.servlet.http.HttpServletResponse class

Example:

javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED //401
javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR //500

Upvotes: 7

Ed J
Ed J

Reputation: 2555

If you're using Spring, the 3.x release has what your looking for: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/http/HttpStatus.html

Upvotes: 23

Greg Noe
Greg Noe

Reputation: 1156

Also check out the Restlet Status class:

http://www.restlet.org/documentation/1.1/api/org/restlet/data/Status.html

Upvotes: 2

Mystic
Mystic

Reputation: 5124

Well, there are static constants of the exact integer values in the HttpURLConnection class

Upvotes: 99

Related Questions