ref: 日志格式
parent
98776d8786
commit
9289f105c8
|
|
@ -6,6 +6,7 @@ import com.czcb.scfs.api.core.exception.TimestampException;
|
||||||
import com.czcb.scfs.api.core.exception.ValidationException;
|
import com.czcb.scfs.api.core.exception.ValidationException;
|
||||||
import com.czcb.scfs.api.core.http.HttpLogger;
|
import com.czcb.scfs.api.core.http.HttpLogger;
|
||||||
import com.czcb.scfs.api.core.http.HttpRequest;
|
import com.czcb.scfs.api.core.http.HttpRequest;
|
||||||
|
import com.czcb.scfs.api.core.http.LogLevel;
|
||||||
import com.czcb.scfs.api.core.http.OriginalResponse;
|
import com.czcb.scfs.api.core.http.OriginalResponse;
|
||||||
import com.czcb.scfs.api.core.util.Strings;
|
import com.czcb.scfs.api.core.util.Strings;
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ public final class DefaultValidator implements Validator {
|
||||||
public DefaultValidator(Profile profile) {
|
public DefaultValidator(Profile profile) {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
this.verifier = profile.getSignature().getVerifier();
|
this.verifier = profile.getSignature().getVerifier();
|
||||||
this.httpLogger = new HttpLogger(profile.getHttpProfile() == null || profile.getHttpProfile().logEnabled());
|
this.httpLogger = new HttpLogger(profile.getHttpProfile() == null ? LogLevel.basic : profile.getHttpProfile().logLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInvalidHttpCode(int httpCode) {
|
private boolean isInvalidHttpCode(int httpCode) {
|
||||||
|
|
@ -59,10 +60,6 @@ public final class DefaultValidator implements Validator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validate(HttpRequest request, OriginalResponse response, Channel channel) {
|
public void validate(HttpRequest request, OriginalResponse response, Channel channel) {
|
||||||
if (isInvalidHttpCode(response.getStatusCode())) {
|
|
||||||
httpLogger.logHttpStatus(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验时间戳
|
// 校验时间戳
|
||||||
validateTimestamp(request, response);
|
validateTimestamp(request, response);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public abstract class AbstractApiClient implements ApiClient {
|
||||||
this.privacy = profile.getPrivacy();
|
this.privacy = profile.getPrivacy();
|
||||||
this.signature = profile.getSignature();
|
this.signature = profile.getSignature();
|
||||||
this.validator = new DefaultValidator(profile);
|
this.validator = new DefaultValidator(profile);
|
||||||
this.httpLogger = new HttpLogger(profile.getHttpProfile() == null || profile.getHttpProfile().logEnabled());
|
this.httpLogger = new HttpLogger(profile.getHttpProfile() == null ? LogLevel.basic : profile.getHttpProfile().logLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -140,9 +140,8 @@ public abstract class AbstractApiClient implements ApiClient {
|
||||||
byte[] secretKey = cipher.getSecretKey();
|
byte[] secretKey = cipher.getSecretKey();
|
||||||
// 密钥进行非对称加密
|
// 密钥进行非对称加密
|
||||||
PrivacyEncryptor encryptor = privacy.getEncryptor();
|
PrivacyEncryptor encryptor = privacy.getEncryptor();
|
||||||
String encryptSecretKey = encryptor.encrypt(Strings.toStr(secretKey));
|
|
||||||
// 加密后的密钥放入到请求头
|
// 加密后的密钥放入到请求头
|
||||||
httpRequest.getHttpHeaders().addHeader(SECRET_KEY, encryptSecretKey);
|
httpRequest.getHttpHeaders().addHeader(SECRET_KEY, encryptor.encrypt(Strings.toStr(secretKey)));
|
||||||
// 加密证书序列号
|
// 加密证书序列号
|
||||||
httpRequest.getHttpHeaders().addHeader(BANK_CERTIFICATE_SERIAL, encryptor.getCertificateSerial());
|
httpRequest.getHttpHeaders().addHeader(BANK_CERTIFICATE_SERIAL, encryptor.getCertificateSerial());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ public class DefaultHttpProfile implements HttpProfile {
|
||||||
// 请求代理
|
// 请求代理
|
||||||
private final Proxy proxy;
|
private final Proxy proxy;
|
||||||
// 是否启用日志打印 默认true
|
// 是否启用日志打印 默认true
|
||||||
private final boolean logEnabled;
|
private final LogLevel logLevel;
|
||||||
// 是否启用压缩
|
// 是否启用压缩
|
||||||
private final boolean compressionEnabled;
|
private final boolean compressionEnabled;
|
||||||
|
|
||||||
|
|
@ -31,13 +31,13 @@ public class DefaultHttpProfile implements HttpProfile {
|
||||||
this.connPool = builder.connPool;
|
this.connPool = builder.connPool;
|
||||||
this.headers = builder.headers;
|
this.headers = builder.headers;
|
||||||
this.proxy = builder.proxy;
|
this.proxy = builder.proxy;
|
||||||
this.logEnabled = builder.logEnabled;
|
this.logLevel = builder.logLevel;
|
||||||
this.compressionEnabled = builder.compressionEnabled;
|
this.compressionEnabled = builder.compressionEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean logEnabled() {
|
public LogLevel logLevel() {
|
||||||
return logEnabled;
|
return logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -82,7 +82,7 @@ public class DefaultHttpProfile implements HttpProfile {
|
||||||
// 请求代理
|
// 请求代理
|
||||||
private Proxy proxy;
|
private Proxy proxy;
|
||||||
// 是否启用日志打印
|
// 是否启用日志打印
|
||||||
private boolean logEnabled = true;
|
private LogLevel logLevel = LogLevel.basic;
|
||||||
// 是否启用压缩
|
// 是否启用压缩
|
||||||
private boolean compressionEnabled = false;
|
private boolean compressionEnabled = false;
|
||||||
|
|
||||||
|
|
@ -111,8 +111,8 @@ public class DefaultHttpProfile implements HttpProfile {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder logEnabled(boolean logEnabled) {
|
public Builder logLevel(LogLevel logLevel) {
|
||||||
this.logEnabled = logEnabled;
|
this.logLevel = logLevel;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,22 @@ import com.czcb.scfs.api.core.util.Strings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.czcb.scfs.api.core.Constants.REQUEST_ID;
|
||||||
|
import static com.czcb.scfs.api.core.http.LogLevel.isFull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author wangwei
|
* @author wangwei
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public class HttpLogger {
|
public class HttpLogger {
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
private final boolean logEnabled;
|
private final LogLevel logLevel;
|
||||||
|
private final boolean logPrefix = false;
|
||||||
|
|
||||||
public HttpLogger(boolean logEnabled) {
|
public HttpLogger(LogLevel logLevel) {
|
||||||
this.logEnabled = logEnabled;
|
this.logLevel = logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,23 +30,27 @@ public class HttpLogger {
|
||||||
* @param httpVersion http 版本
|
* @param httpVersion http 版本
|
||||||
*/
|
*/
|
||||||
protected void logRequest(HttpRequest request, String httpVersion) {
|
protected void logRequest(HttpRequest request, String httpVersion) {
|
||||||
if (!logEnabled) {
|
String logPrefixText = logPrefix(request);
|
||||||
return;
|
logger.info("{}请求:{} {} {}", logPrefixText, request.getHttpMethod(), request.getUrl(), httpVersion);
|
||||||
|
|
||||||
|
if (isFull(logLevel)) {
|
||||||
|
request.getHttpHeaders().getHeaders().forEach((k, v) -> logger.info("{}请求头:{}:{}", logPrefixText, k, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("[{}] 请求行:{} {} {}", request.getId(), request.getHttpMethod(), request.getUrl(), httpVersion);
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
request.getHttpHeaders().getHeaders().forEach((k, v) -> sb.append(k).append("=").append(v).append(";"));
|
|
||||||
logger.info("[{}] 请求头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
|
|
||||||
|
|
||||||
if (request.getRequestBody() instanceof EncryptRequestBody) {
|
if (request.getRequestBody() instanceof EncryptRequestBody) {
|
||||||
EncryptRequestBody body = (EncryptRequestBody) request.getRequestBody();
|
EncryptRequestBody requestBody = (EncryptRequestBody) request.getRequestBody();
|
||||||
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getOriginalBody()));
|
|
||||||
logger.info("[{}] 请求加密报文:{}", request.getId(), Strings.toStr(body.getBody()));
|
String originalBodyText = Strings.toStr(requestBody.getOriginalBody());
|
||||||
|
logger.info("{}请求报文:{}", logPrefixText, originalBodyText);
|
||||||
|
|
||||||
|
if (isFull(logLevel)) {
|
||||||
|
String bodyText = Strings.toStr(requestBody.getBody());
|
||||||
|
logger.info("{}请求加密报文:{}", logPrefixText, bodyText);
|
||||||
|
}
|
||||||
} else if (request.getRequestBody() instanceof JsonRequestBody) {
|
} else if (request.getRequestBody() instanceof JsonRequestBody) {
|
||||||
JsonRequestBody body = (JsonRequestBody) request.getRequestBody();
|
JsonRequestBody requestBody = (JsonRequestBody) request.getRequestBody();
|
||||||
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getBody()));
|
String bodyText = Strings.toStr(requestBody.getBody());
|
||||||
|
logger.info("{}请求报文:{}", logPrefixText, bodyText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,18 +63,26 @@ public class HttpLogger {
|
||||||
* @param <T> 返回类型
|
* @param <T> 返回类型
|
||||||
*/
|
*/
|
||||||
protected <T> void logResponse(HttpRequest request, OriginalResponse originalResponse, HttpResponse<T> response, long duration) {
|
protected <T> void logResponse(HttpRequest request, OriginalResponse originalResponse, HttpResponse<T> response, long duration) {
|
||||||
if (!logEnabled) {
|
String logPrefixText = logPrefix(request);
|
||||||
return;
|
if (isFull(logLevel)) {
|
||||||
|
String reasonPhrase = httpReasonPhrase(originalResponse);
|
||||||
|
logger.info("{}应答:{} {} {}", logPrefixText, originalResponse.getVersion(), originalResponse.getStatusCode(), reasonPhrase);
|
||||||
|
|
||||||
|
response.getHttpHeaders().getHeaders().forEach((k, v) -> logger.info("{}应答头:{}:{}", logPrefixText, k, v));
|
||||||
|
|
||||||
|
String originalBodyText = Strings.toStr(response.getOriginalBody());
|
||||||
|
logger.info("{}应答原始报文:{}", logPrefixText, originalBodyText);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("[{}] 响应行:{} {}", request.getId(), originalResponse.getVersion(), originalResponse.getStatusCode());
|
String requestId = originalResponse.getHttpHeaders().getHeader(REQUEST_ID);
|
||||||
StringBuilder sb = new StringBuilder();
|
logger.info("{}应答-服务端Request-Id:{}", logPrefixText, requestId);
|
||||||
response.getHttpHeaders().getHeaders().forEach((k, v) -> sb.append(k).append("=").append(v).append(";"));
|
|
||||||
logger.info("[{}] 响应头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
|
|
||||||
logger.info("[{}] 响应原始报文:{}", request.getId(), Strings.toStr(response.getOriginalBody()));
|
|
||||||
logger.info("[{}] 响应解密报文:{}", request.getId(), Json.toJson(response.getServiceResponse()));
|
|
||||||
|
|
||||||
logger.info("[{}] 请求-响应耗时(毫秒):{}", request.getId(), duration);
|
String text = Json.toJson(response.getServiceResponse());
|
||||||
|
logger.info("{}应答报文:{}", logPrefixText, text);
|
||||||
|
|
||||||
|
if (isFull(logLevel)) {
|
||||||
|
logger.info("{}请求-应答耗时(毫秒):{}", logPrefixText, duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,18 +91,35 @@ public class HttpLogger {
|
||||||
* @param originalResponse 响应数据
|
* @param originalResponse 响应数据
|
||||||
*/
|
*/
|
||||||
public void logResponseError(HttpRequest request, OriginalResponse originalResponse) {
|
public void logResponseError(HttpRequest request, OriginalResponse originalResponse) {
|
||||||
logger.error("[{}] 响应:{} {}", request.getId(), originalResponse.getVersion(), originalResponse.getStatusCode());
|
String logPrefixText = logPrefix(request);
|
||||||
StringBuilder sb = new StringBuilder();
|
logger.error("{}响应:{} {}", request.getId(), originalResponse.getVersion(), originalResponse.getStatusCode());
|
||||||
originalResponse.getHttpHeaders().getHeaders().forEach((k, v) -> sb.append(k).append("=").append(v).append(";"));
|
if (isFull(logLevel)) {
|
||||||
logger.error("[{}] 响应头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
|
originalResponse.getHttpHeaders().getHeaders().forEach((k, v) -> logger.info("{}请求头:{}:{}", logPrefixText, k, v));
|
||||||
logger.error("[{}] 响应原始报文:{}", request.getId(), Strings.toStr((originalResponse.getBody())));
|
|
||||||
|
String body = Strings.toStr(originalResponse.getBody());
|
||||||
|
logger.error("{}响应原始报文:{}", logPrefixText, body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logHttpStatus(OriginalResponse response) {
|
public String httpReasonPhrase(OriginalResponse response) {
|
||||||
// TODO 打印状态码说明
|
HttpStatus status = HttpStatus.resolve(response.getStatusCode());
|
||||||
|
if (Objects.isNull(status)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return status.getReasonPhrase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logRemoteError(HttpRequest newRequest, String message) {
|
public void logRemoteError(HttpRequest newRequest, String message) {
|
||||||
logger.error("[{}] 远程调用异常:{}", newRequest.getId(), message);
|
String logPrefixText = logPrefix(newRequest);
|
||||||
|
logger.error("{}远程调用异常:{}", logPrefixText, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String logPrefix(HttpRequest request) {
|
||||||
|
if (logPrefix) {
|
||||||
|
return String.format("[%s] ", request.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ public interface HttpProfile {
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
boolean logEnabled();
|
LogLevel logLevel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启压缩
|
* 是否开启压缩
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,665 @@
|
||||||
|
package com.czcb.scfs.api.core.http;
|
||||||
|
|
||||||
|
public enum HttpStatus {
|
||||||
|
CONTINUE(100, Series.INFORMATIONAL, "Continue"),
|
||||||
|
/**
|
||||||
|
* {@code 101 Switching Protocols}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.2.2">HTTP/1.1: Semantics and Content, section 6.2.2</a>
|
||||||
|
*/
|
||||||
|
SWITCHING_PROTOCOLS(101, Series.INFORMATIONAL, "Switching Protocols"),
|
||||||
|
/**
|
||||||
|
* {@code 102 Processing}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2518#section-10.1">WebDAV</a>
|
||||||
|
*/
|
||||||
|
PROCESSING(102, Series.INFORMATIONAL, "Processing"),
|
||||||
|
/**
|
||||||
|
* {@code 103 Checkpoint}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal">A proposal for supporting
|
||||||
|
* resumable POST/PUT HTTP requests in HTTP/1.0</a>
|
||||||
|
*/
|
||||||
|
CHECKPOINT(103, Series.INFORMATIONAL, "Checkpoint"),
|
||||||
|
|
||||||
|
// 2xx Success
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code 200 OK}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">HTTP/1.1: Semantics and Content, section 6.3.1</a>
|
||||||
|
*/
|
||||||
|
OK(200, Series.SUCCESSFUL, "OK"),
|
||||||
|
/**
|
||||||
|
* {@code 201 Created}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.2">HTTP/1.1: Semantics and Content, section 6.3.2</a>
|
||||||
|
*/
|
||||||
|
CREATED(201, Series.SUCCESSFUL, "Created"),
|
||||||
|
/**
|
||||||
|
* {@code 202 Accepted}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.3">HTTP/1.1: Semantics and Content, section 6.3.3</a>
|
||||||
|
*/
|
||||||
|
ACCEPTED(202, Series.SUCCESSFUL, "Accepted"),
|
||||||
|
/**
|
||||||
|
* {@code 203 Non-Authoritative Information}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.4">HTTP/1.1: Semantics and Content, section 6.3.4</a>
|
||||||
|
*/
|
||||||
|
NON_AUTHORITATIVE_INFORMATION(203, Series.SUCCESSFUL, "Non-Authoritative Information"),
|
||||||
|
/**
|
||||||
|
* {@code 204 No Content}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.5">HTTP/1.1: Semantics and Content, section 6.3.5</a>
|
||||||
|
*/
|
||||||
|
NO_CONTENT(204, Series.SUCCESSFUL, "No Content"),
|
||||||
|
/**
|
||||||
|
* {@code 205 Reset Content}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.3.6">HTTP/1.1: Semantics and Content, section 6.3.6</a>
|
||||||
|
*/
|
||||||
|
RESET_CONTENT(205, Series.SUCCESSFUL, "Reset Content"),
|
||||||
|
/**
|
||||||
|
* {@code 206 Partial Content}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7233#section-4.1">HTTP/1.1: Range Requests, section 4.1</a>
|
||||||
|
*/
|
||||||
|
PARTIAL_CONTENT(206, Series.SUCCESSFUL, "Partial Content"),
|
||||||
|
/**
|
||||||
|
* {@code 207 Multi-Status}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4918#section-13">WebDAV</a>
|
||||||
|
*/
|
||||||
|
MULTI_STATUS(207, Series.SUCCESSFUL, "Multi-Status"),
|
||||||
|
/**
|
||||||
|
* {@code 208 Already Reported}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc5842#section-7.1">WebDAV Binding Extensions</a>
|
||||||
|
*/
|
||||||
|
ALREADY_REPORTED(208, Series.SUCCESSFUL, "Already Reported"),
|
||||||
|
/**
|
||||||
|
* {@code 226 IM Used}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc3229#section-10.4.1">Delta encoding in HTTP</a>
|
||||||
|
*/
|
||||||
|
IM_USED(226, Series.SUCCESSFUL, "IM Used"),
|
||||||
|
|
||||||
|
// 3xx Redirection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code 300 Multiple Choices}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.1">HTTP/1.1: Semantics and Content, section 6.4.1</a>
|
||||||
|
*/
|
||||||
|
MULTIPLE_CHOICES(300, Series.REDIRECTION, "Multiple Choices"),
|
||||||
|
/**
|
||||||
|
* {@code 301 Moved Permanently}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.2">HTTP/1.1: Semantics and Content, section 6.4.2</a>
|
||||||
|
*/
|
||||||
|
MOVED_PERMANENTLY(301, Series.REDIRECTION, "Moved Permanently"),
|
||||||
|
/**
|
||||||
|
* {@code 302 Found}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.3">HTTP/1.1: Semantics and Content, section 6.4.3</a>
|
||||||
|
*/
|
||||||
|
FOUND(302, Series.REDIRECTION, "Found"),
|
||||||
|
/**
|
||||||
|
* {@code 302 Moved Temporarily}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc1945#section-9.3">HTTP/1.0, section 9.3</a>
|
||||||
|
* @deprecated in favor of {@link #FOUND} which will be returned from {@code HttpStatus.valueOf(302)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
MOVED_TEMPORARILY(302, Series.REDIRECTION, "Moved Temporarily"),
|
||||||
|
/**
|
||||||
|
* {@code 303 See Other}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.4">HTTP/1.1: Semantics and Content, section 6.4.4</a>
|
||||||
|
*/
|
||||||
|
SEE_OTHER(303, Series.REDIRECTION, "See Other"),
|
||||||
|
/**
|
||||||
|
* {@code 304 Not Modified}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7232#section-4.1">HTTP/1.1: Conditional Requests, section 4.1</a>
|
||||||
|
*/
|
||||||
|
NOT_MODIFIED(304, Series.REDIRECTION, "Not Modified"),
|
||||||
|
/**
|
||||||
|
* {@code 305 Use Proxy}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.5">HTTP/1.1: Semantics and Content, section 6.4.5</a>
|
||||||
|
* @deprecated due to security concerns regarding in-band configuration of a proxy
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
USE_PROXY(305, Series.REDIRECTION, "Use Proxy"),
|
||||||
|
/**
|
||||||
|
* {@code 307 Temporary Redirect}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.4.7">HTTP/1.1: Semantics and Content, section 6.4.7</a>
|
||||||
|
*/
|
||||||
|
TEMPORARY_REDIRECT(307, Series.REDIRECTION, "Temporary Redirect"),
|
||||||
|
/**
|
||||||
|
* {@code 308 Permanent Redirect}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7238">RFC 7238</a>
|
||||||
|
*/
|
||||||
|
PERMANENT_REDIRECT(308, Series.REDIRECTION, "Permanent Redirect"),
|
||||||
|
|
||||||
|
// --- 4xx Client Error ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code 400 Bad Request}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">HTTP/1.1: Semantics and Content, section 6.5.1</a>
|
||||||
|
*/
|
||||||
|
BAD_REQUEST(400, Series.CLIENT_ERROR, "Bad Request"),
|
||||||
|
/**
|
||||||
|
* {@code 401 Unauthorized}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7235#section-3.1">HTTP/1.1: Authentication, section 3.1</a>
|
||||||
|
*/
|
||||||
|
UNAUTHORIZED(401, Series.CLIENT_ERROR, "Unauthorized"),
|
||||||
|
/**
|
||||||
|
* {@code 402 Payment Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.2">HTTP/1.1: Semantics and Content, section 6.5.2</a>
|
||||||
|
*/
|
||||||
|
PAYMENT_REQUIRED(402, Series.CLIENT_ERROR, "Payment Required"),
|
||||||
|
/**
|
||||||
|
* {@code 403 Forbidden}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.3">HTTP/1.1: Semantics and Content, section 6.5.3</a>
|
||||||
|
*/
|
||||||
|
FORBIDDEN(403, Series.CLIENT_ERROR, "Forbidden"),
|
||||||
|
/**
|
||||||
|
* {@code 404 Not Found}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.4">HTTP/1.1: Semantics and Content, section 6.5.4</a>
|
||||||
|
*/
|
||||||
|
NOT_FOUND(404, Series.CLIENT_ERROR, "Not Found"),
|
||||||
|
/**
|
||||||
|
* {@code 405 Method Not Allowed}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.5">HTTP/1.1: Semantics and Content, section 6.5.5</a>
|
||||||
|
*/
|
||||||
|
METHOD_NOT_ALLOWED(405, Series.CLIENT_ERROR, "Method Not Allowed"),
|
||||||
|
/**
|
||||||
|
* {@code 406 Not Acceptable}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.6">HTTP/1.1: Semantics and Content, section 6.5.6</a>
|
||||||
|
*/
|
||||||
|
NOT_ACCEPTABLE(406, Series.CLIENT_ERROR, "Not Acceptable"),
|
||||||
|
/**
|
||||||
|
* {@code 407 Proxy Authentication Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7235#section-3.2">HTTP/1.1: Authentication, section 3.2</a>
|
||||||
|
*/
|
||||||
|
PROXY_AUTHENTICATION_REQUIRED(407, Series.CLIENT_ERROR, "Proxy Authentication Required"),
|
||||||
|
/**
|
||||||
|
* {@code 408 Request Timeout}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.7">HTTP/1.1: Semantics and Content, section 6.5.7</a>
|
||||||
|
*/
|
||||||
|
REQUEST_TIMEOUT(408, Series.CLIENT_ERROR, "Request Timeout"),
|
||||||
|
/**
|
||||||
|
* {@code 409 Conflict}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.8">HTTP/1.1: Semantics and Content, section 6.5.8</a>
|
||||||
|
*/
|
||||||
|
CONFLICT(409, Series.CLIENT_ERROR, "Conflict"),
|
||||||
|
/**
|
||||||
|
* {@code 410 Gone}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.9">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.9</a>
|
||||||
|
*/
|
||||||
|
GONE(410, Series.CLIENT_ERROR, "Gone"),
|
||||||
|
/**
|
||||||
|
* {@code 411 Length Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.10">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.10</a>
|
||||||
|
*/
|
||||||
|
LENGTH_REQUIRED(411, Series.CLIENT_ERROR, "Length Required"),
|
||||||
|
/**
|
||||||
|
* {@code 412 Precondition failed}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7232#section-4.2">
|
||||||
|
* HTTP/1.1: Conditional Requests, section 4.2</a>
|
||||||
|
*/
|
||||||
|
PRECONDITION_FAILED(412, Series.CLIENT_ERROR, "Precondition Failed"),
|
||||||
|
/**
|
||||||
|
* {@code 413 Payload Too Large}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.11">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.11</a>
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
PAYLOAD_TOO_LARGE(413, Series.CLIENT_ERROR, "Payload Too Large"),
|
||||||
|
/**
|
||||||
|
* {@code 413 Request Entity Too Large}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2616#section-10.4.14">HTTP/1.1, section 10.4.14</a>
|
||||||
|
* @deprecated in favor of {@link #PAYLOAD_TOO_LARGE} which will be
|
||||||
|
* returned from {@code HttpStatus.valueOf(413)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
REQUEST_ENTITY_TOO_LARGE(413, Series.CLIENT_ERROR, "Request Entity Too Large"),
|
||||||
|
/**
|
||||||
|
* {@code 414 URI Too Long}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.12">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.12</a>
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
URI_TOO_LONG(414, Series.CLIENT_ERROR, "URI Too Long"),
|
||||||
|
/**
|
||||||
|
* {@code 414 Request-URI Too Long}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2616#section-10.4.15">HTTP/1.1, section 10.4.15</a>
|
||||||
|
* @deprecated in favor of {@link #URI_TOO_LONG} which will be returned from {@code HttpStatus.valueOf(414)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
REQUEST_URI_TOO_LONG(414, Series.CLIENT_ERROR, "Request-URI Too Long"),
|
||||||
|
/**
|
||||||
|
* {@code 415 Unsupported Media Type}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.13">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.13</a>
|
||||||
|
*/
|
||||||
|
UNSUPPORTED_MEDIA_TYPE(415, Series.CLIENT_ERROR, "Unsupported Media Type"),
|
||||||
|
/**
|
||||||
|
* {@code 416 Requested Range Not Satisfiable}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7233#section-4.4">HTTP/1.1: Range Requests, section 4.4</a>
|
||||||
|
*/
|
||||||
|
REQUESTED_RANGE_NOT_SATISFIABLE(416, Series.CLIENT_ERROR, "Requested range not satisfiable"),
|
||||||
|
/**
|
||||||
|
* {@code 417 Expectation Failed}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.14">
|
||||||
|
* HTTP/1.1: Semantics and Content, section 6.5.14</a>
|
||||||
|
*/
|
||||||
|
EXPECTATION_FAILED(417, Series.CLIENT_ERROR, "Expectation Failed"),
|
||||||
|
/**
|
||||||
|
* {@code 418 I'm a teapot}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2324#section-2.3.2">HTCPCP/1.0</a>
|
||||||
|
*/
|
||||||
|
I_AM_A_TEAPOT(418, Series.CLIENT_ERROR, "I'm a teapot"),
|
||||||
|
/**
|
||||||
|
* @deprecated See
|
||||||
|
* <a href="https://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">
|
||||||
|
* WebDAV Draft Changes</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
INSUFFICIENT_SPACE_ON_RESOURCE(419, Series.CLIENT_ERROR, "Insufficient Space On Resource"),
|
||||||
|
/**
|
||||||
|
* @deprecated See
|
||||||
|
* <a href="https://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">
|
||||||
|
* WebDAV Draft Changes</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
METHOD_FAILURE(420, Series.CLIENT_ERROR, "Method Failure"),
|
||||||
|
/**
|
||||||
|
* @deprecated See <a href="https://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">
|
||||||
|
* WebDAV Draft Changes</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
DESTINATION_LOCKED(421, Series.CLIENT_ERROR, "Destination Locked"),
|
||||||
|
/**
|
||||||
|
* {@code 422 Unprocessable Entity}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4918#section-11.2">WebDAV</a>
|
||||||
|
*/
|
||||||
|
UNPROCESSABLE_ENTITY(422, Series.CLIENT_ERROR, "Unprocessable Entity"),
|
||||||
|
/**
|
||||||
|
* {@code 423 Locked}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4918#section-11.3">WebDAV</a>
|
||||||
|
*/
|
||||||
|
LOCKED(423, Series.CLIENT_ERROR, "Locked"),
|
||||||
|
/**
|
||||||
|
* {@code 424 Failed Dependency}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4918#section-11.4">WebDAV</a>
|
||||||
|
*/
|
||||||
|
FAILED_DEPENDENCY(424, Series.CLIENT_ERROR, "Failed Dependency"),
|
||||||
|
/**
|
||||||
|
* {@code 425 Too Early}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc8470">RFC 8470</a>
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
TOO_EARLY(425, Series.CLIENT_ERROR, "Too Early"),
|
||||||
|
/**
|
||||||
|
* {@code 426 Upgrade Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2817#section-6">Upgrading to TLS Within HTTP/1.1</a>
|
||||||
|
*/
|
||||||
|
UPGRADE_REQUIRED(426, Series.CLIENT_ERROR, "Upgrade Required"),
|
||||||
|
/**
|
||||||
|
* {@code 428 Precondition Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc6585#section-3">Additional HTTP Status Codes</a>
|
||||||
|
*/
|
||||||
|
PRECONDITION_REQUIRED(428, Series.CLIENT_ERROR, "Precondition Required"),
|
||||||
|
/**
|
||||||
|
* {@code 429 Too Many Requests}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc6585#section-4">Additional HTTP Status Codes</a>
|
||||||
|
*/
|
||||||
|
TOO_MANY_REQUESTS(429, Series.CLIENT_ERROR, "Too Many Requests"),
|
||||||
|
/**
|
||||||
|
* {@code 431 Request Header Fields Too Large}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc6585#section-5">Additional HTTP Status Codes</a>
|
||||||
|
*/
|
||||||
|
REQUEST_HEADER_FIELDS_TOO_LARGE(431, Series.CLIENT_ERROR, "Request Header Fields Too Large"),
|
||||||
|
/**
|
||||||
|
* {@code 451 Unavailable For Legal Reasons}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/draft-ietf-httpbis-legally-restricted-status-04">
|
||||||
|
* An HTTP Status Code to Report Legal Obstacles</a>
|
||||||
|
* @since 4.3
|
||||||
|
*/
|
||||||
|
UNAVAILABLE_FOR_LEGAL_REASONS(451, Series.CLIENT_ERROR, "Unavailable For Legal Reasons"),
|
||||||
|
|
||||||
|
// --- 5xx Server Error ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code 500 Internal Server Error}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.1">HTTP/1.1: Semantics and Content, section 6.6.1</a>
|
||||||
|
*/
|
||||||
|
INTERNAL_SERVER_ERROR(500, Series.SERVER_ERROR, "Internal Server Error"),
|
||||||
|
/**
|
||||||
|
* {@code 501 Not Implemented}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.2">HTTP/1.1: Semantics and Content, section 6.6.2</a>
|
||||||
|
*/
|
||||||
|
NOT_IMPLEMENTED(501, Series.SERVER_ERROR, "Not Implemented"),
|
||||||
|
/**
|
||||||
|
* {@code 502 Bad Gateway}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.3">HTTP/1.1: Semantics and Content, section 6.6.3</a>
|
||||||
|
*/
|
||||||
|
BAD_GATEWAY(502, Series.SERVER_ERROR, "Bad Gateway"),
|
||||||
|
/**
|
||||||
|
* {@code 503 Service Unavailable}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.4">HTTP/1.1: Semantics and Content, section 6.6.4</a>
|
||||||
|
*/
|
||||||
|
SERVICE_UNAVAILABLE(503, Series.SERVER_ERROR, "Service Unavailable"),
|
||||||
|
/**
|
||||||
|
* {@code 504 Gateway Timeout}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.5">HTTP/1.1: Semantics and Content, section 6.6.5</a>
|
||||||
|
*/
|
||||||
|
GATEWAY_TIMEOUT(504, Series.SERVER_ERROR, "Gateway Timeout"),
|
||||||
|
/**
|
||||||
|
* {@code 505 HTTP Version Not Supported}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc7231#section-6.6.6">HTTP/1.1: Semantics and Content, section 6.6.6</a>
|
||||||
|
*/
|
||||||
|
HTTP_VERSION_NOT_SUPPORTED(505, Series.SERVER_ERROR, "HTTP Version not supported"),
|
||||||
|
/**
|
||||||
|
* {@code 506 Variant Also Negotiates}
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2295#section-8.1">Transparent Content Negotiation</a>
|
||||||
|
*/
|
||||||
|
VARIANT_ALSO_NEGOTIATES(506, Series.SERVER_ERROR, "Variant Also Negotiates"),
|
||||||
|
/**
|
||||||
|
* {@code 507 Insufficient Storage}
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4918#section-11.5">WebDAV</a>
|
||||||
|
*/
|
||||||
|
INSUFFICIENT_STORAGE(507, Series.SERVER_ERROR, "Insufficient Storage"),
|
||||||
|
/**
|
||||||
|
* {@code 508 Loop Detected}
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc5842#section-7.2">WebDAV Binding Extensions</a>
|
||||||
|
*/
|
||||||
|
LOOP_DETECTED(508, Series.SERVER_ERROR, "Loop Detected"),
|
||||||
|
/**
|
||||||
|
* {@code 509 Bandwidth Limit Exceeded}
|
||||||
|
*/
|
||||||
|
BANDWIDTH_LIMIT_EXCEEDED(509, Series.SERVER_ERROR, "Bandwidth Limit Exceeded"),
|
||||||
|
/**
|
||||||
|
* {@code 510 Not Extended}
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc2774#section-7">HTTP Extension Framework</a>
|
||||||
|
*/
|
||||||
|
NOT_EXTENDED(510, Series.SERVER_ERROR, "Not Extended"),
|
||||||
|
/**
|
||||||
|
* {@code 511 Network Authentication Required}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc6585#section-6">Additional HTTP Status Codes</a>
|
||||||
|
*/
|
||||||
|
NETWORK_AUTHENTICATION_REQUIRED(511, Series.SERVER_ERROR, "Network Authentication Required");
|
||||||
|
|
||||||
|
|
||||||
|
private static final HttpStatus[] VALUES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
VALUES = values();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private final Series series;
|
||||||
|
|
||||||
|
private final String reasonPhrase;
|
||||||
|
|
||||||
|
HttpStatus(int value, Series series, String reasonPhrase) {
|
||||||
|
this.value = value;
|
||||||
|
this.series = series;
|
||||||
|
this.reasonPhrase = reasonPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the integer value of this status code.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTTP status series of this status code.
|
||||||
|
*
|
||||||
|
* @see HttpStatus.Series
|
||||||
|
*/
|
||||||
|
public Series series() {
|
||||||
|
return this.series;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the reason phrase of this status code.
|
||||||
|
*/
|
||||||
|
public String getReasonPhrase() {
|
||||||
|
return this.reasonPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #series()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean is1xxInformational() {
|
||||||
|
return (series() == Series.INFORMATIONAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #series()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean is2xxSuccessful() {
|
||||||
|
return (series() == Series.SUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #series()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean is3xxRedirection() {
|
||||||
|
return (series() == Series.REDIRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #series()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean is4xxClientError() {
|
||||||
|
return (series() == Series.CLIENT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #series()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean is5xxServerError() {
|
||||||
|
return (series() == Series.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this status code is in the HTTP series
|
||||||
|
* <p>This is a shortcut for checking the value of {@link #series()}.
|
||||||
|
*
|
||||||
|
* @see #is4xxClientError()
|
||||||
|
* @see #is5xxServerError()
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public boolean isError() {
|
||||||
|
return (is4xxClientError() || is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string representation of this status code.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.value + " " + name();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@code HttpStatus} enum constant with the specified numeric value.
|
||||||
|
*
|
||||||
|
* @param statusCode the numeric value of the enum to be returned
|
||||||
|
* @return the enum constant with the specified numeric value
|
||||||
|
* @throws IllegalArgumentException if this enum has no constant for the specified numeric value
|
||||||
|
*/
|
||||||
|
public static HttpStatus valueOf(int statusCode) {
|
||||||
|
HttpStatus status = resolve(statusCode);
|
||||||
|
if (status == null) {
|
||||||
|
throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the given status code to an {@code HttpStatus}, if possible.
|
||||||
|
*
|
||||||
|
* @param statusCode the HTTP status code (potentially non-standard)
|
||||||
|
* @return the corresponding {@code HttpStatus}, or {@code null} if not found
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public static HttpStatus resolve(int statusCode) {
|
||||||
|
// Use cached VALUES instead of values() to prevent array allocation.
|
||||||
|
for (HttpStatus status : VALUES) {
|
||||||
|
if (status.value == statusCode) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumeration of HTTP status series.
|
||||||
|
* <p>Retrievable via {@link HttpStatus#series()}.
|
||||||
|
*/
|
||||||
|
public enum Series {
|
||||||
|
|
||||||
|
INFORMATIONAL(1),
|
||||||
|
SUCCESSFUL(2),
|
||||||
|
REDIRECTION(3),
|
||||||
|
CLIENT_ERROR(4),
|
||||||
|
SERVER_ERROR(5);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
Series(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the integer value of this status series. Ranges from 1 to 5.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@code Series} enum constant for the supplied {@code HttpStatus}.
|
||||||
|
*
|
||||||
|
* @param status a standard HTTP status enum constant
|
||||||
|
* @return the {@code Series} enum constant for the supplied {@code HttpStatus}
|
||||||
|
* @deprecated as of 5.3, in favor of invoking {@link HttpStatus#series()} directly
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static Series valueOf(HttpStatus status) {
|
||||||
|
return status.series;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@code Series} enum constant for the supplied status code.
|
||||||
|
*
|
||||||
|
* @param statusCode the HTTP status code (potentially non-standard)
|
||||||
|
* @return the {@code Series} enum constant for the supplied status code
|
||||||
|
* @throws IllegalArgumentException if this enum has no corresponding constant
|
||||||
|
*/
|
||||||
|
public static Series valueOf(int statusCode) {
|
||||||
|
Series series = resolve(statusCode);
|
||||||
|
if (series == null) {
|
||||||
|
throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
|
||||||
|
}
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the given status code to an {@code HttpStatus.Series}, if possible.
|
||||||
|
*
|
||||||
|
* @param statusCode the HTTP status code (potentially non-standard)
|
||||||
|
* @return the corresponding {@code Series}, or {@code null} if not found
|
||||||
|
* @since 5.1.3
|
||||||
|
*/
|
||||||
|
public static Series resolve(int statusCode) {
|
||||||
|
int seriesCode = statusCode / 100;
|
||||||
|
for (Series series : values()) {
|
||||||
|
if (series.value == seriesCode) {
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.czcb.scfs.api.core.http;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public enum LogLevel {
|
||||||
|
basic, full;
|
||||||
|
|
||||||
|
public static boolean isFull(LogLevel logLevel) {
|
||||||
|
return Objects.equals(full, logLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ class ApiClientBuilderTest {
|
||||||
.build(),
|
.build(),
|
||||||
new DefaultHttpProfile.Builder()
|
new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -142,7 +142,7 @@ class ApiClientBuilderTest {
|
||||||
.port("1000")
|
.port("1000")
|
||||||
.build())
|
.build())
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class DefaultHttpProfileTest {
|
||||||
.headers(data)
|
.headers(data)
|
||||||
.compressionEnabled(true)
|
.compressionEnabled(true)
|
||||||
.online(true)
|
.online(true)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.host("http://10.133.129.74:8761/")
|
.host("http://10.133.129.74:8761/")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ class DefaultHttpProfileTest {
|
||||||
|
|
||||||
Assertions.assertTrue(httpProfile.compressionEnabled());
|
Assertions.assertTrue(httpProfile.compressionEnabled());
|
||||||
Assertions.assertTrue(httpProfile.online());
|
Assertions.assertTrue(httpProfile.online());
|
||||||
Assertions.assertTrue(httpProfile.logEnabled());
|
Assertions.assertEquals(LogLevel.basic, httpProfile.logLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class ApacheHttpclientProxyTest {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class ApacheHttpclientTest {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(compressionEnabled)
|
.compressionEnabled(compressionEnabled)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class ApacheHttpclientTestProxyTest {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class ApacheHttpclientV2Test {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class ApacheHttpclientV3Test {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import com.czcb.scfs.api.core.Profile;
|
||||||
import com.czcb.scfs.api.core.cipher.*;
|
import com.czcb.scfs.api.core.cipher.*;
|
||||||
import com.czcb.scfs.api.core.http.ApiClientBuilder;
|
import com.czcb.scfs.api.core.http.ApiClientBuilder;
|
||||||
import com.czcb.scfs.api.core.http.DefaultHttpProfile;
|
import com.czcb.scfs.api.core.http.DefaultHttpProfile;
|
||||||
|
import com.czcb.scfs.api.core.http.LogLevel;
|
||||||
import com.czcb.scfs.api.core.util.DateTimes;
|
import com.czcb.scfs.api.core.util.DateTimes;
|
||||||
import com.czcb.scfs.api.core.util.Nonce;
|
import com.czcb.scfs.api.core.util.Nonce;
|
||||||
import com.czcb.scfs.api.core.util.Strings;
|
import com.czcb.scfs.api.core.util.Strings;
|
||||||
|
|
@ -52,7 +53,7 @@ public class MockResponse {
|
||||||
.appNo("100000")
|
.appNo("100000")
|
||||||
.build(), new DefaultHttpProfile.Builder()
|
.build(), new DefaultHttpProfile.Builder()
|
||||||
.online(false)
|
.online(false)
|
||||||
.logEnabled(true)
|
.logLevel(LogLevel.basic)
|
||||||
.compressionEnabled(false)
|
.compressionEnabled(false)
|
||||||
.host("http://127.0.0.1:8888")
|
.host("http://127.0.0.1:8888")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public abstract class AbstractAutoConfiguration {
|
||||||
.online(getProperties().getOnline())
|
.online(getProperties().getOnline())
|
||||||
.host(getProperties().getHost())
|
.host(getProperties().getHost())
|
||||||
.headers(getProperties().getHttpclient().getHeaders())
|
.headers(getProperties().getHttpclient().getHeaders())
|
||||||
.logEnabled(getProperties().getHttpclient().getLogEnabled())
|
.logLevel(getProperties().getHttpclient().getLogLevel())
|
||||||
.compressionEnabled(getProperties().getHttpclient().getCompressionEnabled())
|
.compressionEnabled(getProperties().getHttpclient().getCompressionEnabled())
|
||||||
.proxy(proxy.build())
|
.proxy(proxy.build())
|
||||||
.connPool(connPool)
|
.connPool(connPool)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.czcb.scfs.spring.boot.starter;
|
package com.czcb.scfs.spring.boot.starter;
|
||||||
|
|
||||||
import com.czcb.scfs.api.core.cipher.StoreType;
|
import com.czcb.scfs.api.core.cipher.StoreType;
|
||||||
|
import com.czcb.scfs.api.core.http.LogLevel;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -160,9 +161,9 @@ public class ScfsApiGatewayProperties {
|
||||||
|
|
||||||
public static class Httpclient {
|
public static class Httpclient {
|
||||||
/**
|
/**
|
||||||
* 打印请求日志 默认 true
|
* 请求日志打印级别 默认 basic
|
||||||
*/
|
*/
|
||||||
private Boolean logEnabled = true;
|
private LogLevel logLevel = LogLevel.basic;
|
||||||
/**
|
/**
|
||||||
* 请求压缩 默认 false
|
* 请求压缩 默认 false
|
||||||
*/
|
*/
|
||||||
|
|
@ -183,12 +184,12 @@ public class ScfsApiGatewayProperties {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> headers = new HashMap<>();
|
private Map<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
public Boolean getLogEnabled() {
|
public LogLevel getLogLevel() {
|
||||||
return logEnabled;
|
return logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLogEnabled(Boolean logEnabled) {
|
public void setLogLevel(LogLevel logLevel) {
|
||||||
this.logEnabled = logEnabled;
|
this.logLevel = logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getCompressionEnabled() {
|
public Boolean getCompressionEnabled() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.czcb.scfs.spring.boot.starter;
|
package com.czcb.scfs.spring.boot.starter;
|
||||||
|
|
||||||
import com.czcb.scfs.api.core.cipher.StoreType;
|
import com.czcb.scfs.api.core.cipher.StoreType;
|
||||||
|
import com.czcb.scfs.api.core.http.LogLevel;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -65,15 +66,15 @@ class ScfsApiGatewayPropertiesTest {
|
||||||
httpclient.setConnPool(connPool);
|
httpclient.setConnPool(connPool);
|
||||||
|
|
||||||
httpclient.setCompressionEnabled(false);
|
httpclient.setCompressionEnabled(false);
|
||||||
httpclient.setLogEnabled(false);
|
httpclient.setLogLevel(LogLevel.full);
|
||||||
ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties();
|
ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties();
|
||||||
properties.setHttpclient(httpclient);
|
properties.setHttpclient(httpclient);
|
||||||
|
|
||||||
Assertions.assertNotNull(properties.getHttpclient());
|
Assertions.assertNotNull(properties.getHttpclient());
|
||||||
Assertions.assertFalse(properties.getHttpclient().getCompressionEnabled());
|
Assertions.assertFalse(properties.getHttpclient().getCompressionEnabled());
|
||||||
Assertions.assertFalse(properties.getHttpclient().getLogEnabled());
|
Assertions.assertEquals(LogLevel.full, properties.getHttpclient().getLogLevel());
|
||||||
|
|
||||||
assertThatJson("{\"logEnabled\":false,\"compressionEnabled\":false," +
|
assertThatJson("{\"logLevel\":\"full\",\"compressionEnabled\":false," +
|
||||||
"\"connPool\":{\"maxRequests\":100,\"maxRequestPerHost\":100,\"connectTimeout\":100,\"socketTimeout\":100}," +
|
"\"connPool\":{\"maxRequests\":100,\"maxRequestPerHost\":100,\"connectTimeout\":100,\"socketTimeout\":100}," +
|
||||||
"\"proxy\":{\"enabled\":true,\"host\":\"128.0.0.1\",\"port\":\"1000\",\"username\":\"name\",\"password\":\"123456\",\"scheme\":\"https\"}," +
|
"\"proxy\":{\"enabled\":true,\"host\":\"128.0.0.1\",\"port\":\"1000\",\"username\":\"name\",\"password\":\"123456\",\"scheme\":\"https\"}," +
|
||||||
"\"headers\":{\"aa\":\"123456\"}}")
|
"\"headers\":{\"aa\":\"123456\"}}")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.czcb.scfs.spring.boot.starter;
|
package com.czcb.scfs.spring.boot.starter;
|
||||||
|
|
||||||
import com.czcb.scfs.api.core.cipher.StoreType;
|
import com.czcb.scfs.api.core.cipher.StoreType;
|
||||||
|
import com.czcb.scfs.api.core.http.LogLevel;
|
||||||
import org.assertj.core.util.Lists;
|
import org.assertj.core.util.Lists;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -42,7 +43,7 @@ class SmConfigurationTest {
|
||||||
connPool.setSocketTimeout(100);
|
connPool.setSocketTimeout(100);
|
||||||
httpclient.setConnPool(connPool);
|
httpclient.setConnPool(connPool);
|
||||||
httpclient.setCompressionEnabled(false);
|
httpclient.setCompressionEnabled(false);
|
||||||
httpclient.setLogEnabled(false);
|
httpclient.setLogLevel(LogLevel.basic);
|
||||||
properties.setHttpclient(httpclient);
|
properties.setHttpclient(httpclient);
|
||||||
|
|
||||||
ScfsApiGatewayProperties.Channel channel = new ScfsApiGatewayProperties.Channel();
|
ScfsApiGatewayProperties.Channel channel = new ScfsApiGatewayProperties.Channel();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue