From 87537ce397204bd9cf8778ad75c00a3e962e94de Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Thu, 20 Nov 2014 19:41:32 +0900 Subject: [PATCH] Add HttpStatusClass Related: #3157 Motivation: It should be convenient to have an easy way to classify an HttpResponseStatus based on the first digit of the HTTP status code, as defined in the RFC 2616: - Information 1xx - Success 2xx - Redirection 3xx - Client Error 4xx - Server Error 5xx Modification: - Add HttpStatusClass - Add HttpResponseStatus.codeClass() that returns the class of the HTTP status code - Remove HttpResponseStatus.isInformational() Result: It's easier to determine the class of an HTTP status --- .../codec/http/HttpResponseStatus.java | 41 +++---- .../handler/codec/http/HttpStatusClass.java | 100 ++++++++++++++++++ .../http2/InboundHttp2ToHttpAdapter.java | 3 +- 3 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java index 85ec607729..feb7b5ecac 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java @@ -435,25 +435,7 @@ public class HttpResponseStatus implements Comparable { return NETWORK_AUTHENTICATION_REQUIRED; } - final String reasonPhrase; - - if (code < 100) { - reasonPhrase = "Unknown Status"; - } else if (code < 200) { - reasonPhrase = "Informational"; - } else if (code < 300) { - reasonPhrase = "Successful"; - } else if (code < 400) { - reasonPhrase = "Redirection"; - } else if (code < 500) { - reasonPhrase = "Client Error"; - } else if (code < 600) { - reasonPhrase = "Server Error"; - } else { - reasonPhrase = "Unknown Status"; - } - - return new HttpResponseStatus(code, reasonPhrase + " (" + code + ')'); + return new HttpResponseStatus(code); } /** @@ -488,13 +470,20 @@ public class HttpResponseStatus implements Comparable { private final int code; private final AsciiString codeAsText; + private HttpStatusClass codeClass; private final String reasonPhrase; private final byte[] bytes; /** - * Creates a new instance with the specified {@code code} and its - * {@code reasonPhrase}. + * Creates a new instance with the specified {@code code} and the auto-generated default reason phrase. + */ + private HttpResponseStatus(int code) { + this(code, HttpStatusClass.valueOf(code).defaultReasonPhrase() + " (" + code + ')', false); + } + + /** + * Creates a new instance with the specified {@code code} and its {@code reasonPhrase}. */ public HttpResponseStatus(int code, String reasonPhrase) { this(code, reasonPhrase, false); @@ -553,10 +542,14 @@ public class HttpResponseStatus implements Comparable { } /** - * Determine if the status code is of the informational class (1xx) + * Returns the class of this {@link HttpResponseStatus} */ - public boolean isInformational() { - return code >= 100 && code < 200; + public HttpStatusClass codeClass() { + HttpStatusClass type = this.codeClass; + if (type == null) { + this.codeClass = type = HttpStatusClass.valueOf(code); + } + return type; } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java new file mode 100644 index 0000000000..62d9092fb4 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java @@ -0,0 +1,100 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.AsciiString; + +/** + * The class of HTTP status. + */ +public enum HttpStatusClass { + /** + * The informational class (1xx) + */ + INFORMATIONAL(100, 200, "Informational"), + /** + * The success class (2xx) + */ + SUCCESS(200, 300, "Success"), + /** + * The redirection class (3xx) + */ + REDIRECTION(300, 400, "Redirection"), + /** + * The client error class (4xx) + */ + CLIENT_ERROR(400, 500, "Client Error"), + /** + * The server error class (5xx) + */ + SERVER_ERROR(500, 600, "Server Error"), + /** + * The unknown class + */ + UNKNOWN(0, 0, "Unknown Status") { + @Override + public boolean contains(int code) { + return code < 100 || code >= 600; + } + }; + + /** + * Returns the class of the specified HTTP status code. + */ + public static HttpStatusClass valueOf(int code) { + if (INFORMATIONAL.contains(code)) { + return INFORMATIONAL; + } + if (SUCCESS.contains(code)) { + return SUCCESS; + } + if (REDIRECTION.contains(code)) { + return REDIRECTION; + } + if (CLIENT_ERROR.contains(code)) { + return CLIENT_ERROR; + } + if (SERVER_ERROR.contains(code)) { + return SERVER_ERROR; + } + return UNKNOWN; + } + + private final int min; + private final int max; + private final AsciiString defaultReasonPhrase; + + HttpStatusClass(int min, int max, String defaultReasonPhrase) { + this.min = min; + this.max = max; + this.defaultReasonPhrase = new AsciiString(defaultReasonPhrase); + } + + /** + * Returns {@code true} if and only if the specified HTTP status code falls into this class. + */ + public boolean contains(int code) { + return code >= min && code < max; + } + + /** + * Returns the default reason phrase of this HTTP status class. + */ + AsciiString defaultReasonPhrase() { + return defaultReasonPhrase; + } +} diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java index db9b2bc9f4..7eeb465d1f 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java @@ -22,6 +22,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderUtil; +import io.netty.handler.codec.http.HttpStatusClass; import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; import static io.netty.util.internal.ObjectUtil.*; @@ -37,7 +38,7 @@ public class InboundHttp2ToHttpAdapter extends Http2EventAdapter { @Override public boolean mustSendImmediately(FullHttpMessage msg) { if (msg instanceof FullHttpResponse) { - return ((FullHttpResponse) msg).status().isInformational(); + return ((FullHttpResponse) msg).status().codeClass() == HttpStatusClass.INFORMATIONAL; } if (msg instanceof FullHttpRequest) { return msg.headers().contains(HttpHeaderNames.EXPECT);