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
This commit is contained in:
Trustin Lee 2014-11-20 19:41:32 +09:00
parent 1025245a74
commit 87537ce397
3 changed files with 119 additions and 25 deletions

View File

@ -435,25 +435,7 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
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<HttpResponseStatus> {
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<HttpResponseStatus> {
}
/**
* 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

View File

@ -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;
}
}

View File

@ -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);