Browse Source

Introduce HttpStatusCode interface

This commit introduces HttpStatusCode, an interface implemented by
HttpStatus. Instances of HttpStatusCode are obtained via static
valueOf(int) factory method, returning a HttpStatus enum entry if
available, and a default implementation otherwise.

The underlying reason behind this change is HTTP status codes are not
enumerable, but instead range from 100-999.

Closes gh-28214
pull/28225/head
Arjen Poutsma 4 years ago
parent
commit
ca4b6e86a4
  1. 105
      spring-web/src/main/java/org/springframework/http/DefaultHttpStatusCode.java
  2. 56
      spring-web/src/main/java/org/springframework/http/HttpStatus.java
  3. 96
      spring-web/src/main/java/org/springframework/http/HttpStatusCode.java

105
spring-web/src/main/java/org/springframework/http/DefaultHttpStatusCode.java

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed 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
*
* https://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 org.springframework.http;
import java.io.Serializable;
import org.jetbrains.annotations.NotNull;
/**
* Default implementation of {@link HttpStatusCode}.
*
* @author Arjen Poutsma
* @since 6.0
*/
final class DefaultHttpStatusCode
implements HttpStatusCode, Comparable<HttpStatusCode>, Serializable {
private static final long serialVersionUID = 7017664779360718111L;
private final int value;
public DefaultHttpStatusCode(int value) {
this.value = value;
}
@Override
public int value() {
return this.value;
}
@Override
public boolean is1xxInformational() {
return hundreds() == 1;
}
@Override
public boolean is2xxSuccessful() {
return hundreds() == 2;
}
@Override
public boolean is3xxRedirection() {
return hundreds() == 3;
}
@Override
public boolean is4xxClientError() {
return hundreds() == 4;
}
@Override
public boolean is5xxServerError() {
return hundreds() == 5;
}
@Override
public boolean isError() {
int hundreds = hundreds();
return hundreds == 4 || hundreds == 5;
}
private int hundreds() {
return this.value / 100;
}
@Override
public int compareTo(@NotNull HttpStatusCode o) {
return Integer.compare(this.value, o.value());
}
@Override
public int hashCode() {
return this.value;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof HttpStatusCode other) {
return this.value == other.value();
}
else {
return false;
}
}
@Override
public String toString() {
return Integer.toString(this.value);
}
}

56
spring-web/src/main/java/org/springframework/http/HttpStatus.java

@ -31,7 +31,7 @@ import org.springframework.lang.Nullable; @@ -31,7 +31,7 @@ import org.springframework.lang.Nullable;
* @see <a href="https://www.iana.org/assignments/http-status-codes">HTTP Status Code Registry</a>
* @see <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">List of HTTP status codes - Wikipedia</a>
*/
public enum HttpStatus {
public enum HttpStatus implements HttpStatusCode {
// 1xx Informational
@ -436,9 +436,7 @@ public enum HttpStatus { @@ -436,9 +436,7 @@ public enum HttpStatus {
}
/**
* Return the integer value of this status code.
*/
@Override
public int value() {
return this.value;
}
@ -458,70 +456,32 @@ public enum HttpStatus { @@ -458,70 +456,32 @@ public enum HttpStatus {
return this.reasonPhrase;
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#INFORMATIONAL}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 4.0
* @see #series()
*/
@Override
public boolean is1xxInformational() {
return (series() == Series.INFORMATIONAL);
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#SUCCESSFUL}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 4.0
* @see #series()
*/
@Override
public boolean is2xxSuccessful() {
return (series() == Series.SUCCESSFUL);
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#REDIRECTION}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 4.0
* @see #series()
*/
@Override
public boolean is3xxRedirection() {
return (series() == Series.REDIRECTION);
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 4.0
* @see #series()
*/
@Override
public boolean is4xxClientError() {
return (series() == Series.CLIENT_ERROR);
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 4.0
* @see #series()
*/
@Override
public boolean is5xxServerError() {
return (series() == Series.SERVER_ERROR);
}
/**
* Whether this status code is in the HTTP series
* {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}.
* <p>This is a shortcut for checking the value of {@link #series()}.
* @since 5.0
* @see #is4xxClientError()
* @see #is5xxServerError()
*/
@Override
public boolean isError() {
return (is4xxClientError() || is5xxServerError());
}

96
spring-web/src/main/java/org/springframework/http/HttpStatusCode.java

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed 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
*
* https://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 org.springframework.http;
import org.springframework.util.Assert;
/**
* Represents an HTTP response status code. Implemented by {@link HttpStatus},
* but defined as interface to allow for values not in that enumeration.
*
* @author Arjen Poutsma
* @since 6.0
* @see <a href="https://www.iana.org/assignments/http-status-codes">HTTP Status Code Registry</a>
* @see <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">List of HTTP status codes - Wikipedia</a>
*/
public sealed interface HttpStatusCode permits DefaultHttpStatusCode, HttpStatus {
/**
* Return the integer value of this status code.
*/
int value();
/**
* Whether this status code is in the Informational class ({@code 1xx}).
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.1">RFC 2616</a>
*/
boolean is1xxInformational();
/**
* Whether this status code is in the Successful class ({@code 2xx}).
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.2">RFC 2616</a>
*/
boolean is2xxSuccessful();
/**
* Whether this status code is in the Redirection class ({@code 3xx}).
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.3">RFC 2616</a>
*/
boolean is3xxRedirection();
/**
* Whether this status code is in the Client Error class ({@code 4xx}).
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.4">RFC 2616</a>
*/
boolean is4xxClientError();
/**
* Whether this status code is in the Server Error class ({@code 5xx}).
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.5">RFC 2616</a>
*/
boolean is5xxServerError();
/**
* Whether this status code is in the Client or Server Error class
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.4">RFC 2616</a>
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10.3">RFC 2616</a>
* ({@code 4xx} or {@code 5xx}).
* @see #is4xxClientError()
* @see #is5xxServerError()
*/
boolean isError();
/**
* Return an {@code HttpStatusCode} object for the given integer value.
* @param code the status code as integer
* @return the corresponding {@code HttpStatusCode}
* @throws IllegalArgumentException if {@code code} is not a three-digit
* positive number
*/
static HttpStatusCode valueOf(int code) {
Assert.isTrue(code >= 100 && code <= 999, "Code '" + code + "' should be a thee-digit positive integer");
HttpStatus status = HttpStatus.resolve(code);
if (status != null) {
return status;
}
else {
return new DefaultHttpStatusCode(code);
}
}
}
Loading…
Cancel
Save