ref: 日志格式

main
13009 2024-04-10 11:23:55 +08:00
parent 98776d8786
commit 9289f105c8
19 changed files with 781 additions and 70 deletions

View File

@ -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.http.HttpLogger;
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.util.Strings;
@ -30,7 +31,7 @@ public final class DefaultValidator implements Validator {
public DefaultValidator(Profile profile) {
this.profile = profile;
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) {
@ -59,10 +60,6 @@ public final class DefaultValidator implements Validator {
@Override
public void validate(HttpRequest request, OriginalResponse response, Channel channel) {
if (isInvalidHttpCode(response.getStatusCode())) {
httpLogger.logHttpStatus(response);
}
// 校验时间戳
validateTimestamp(request, response);

View File

@ -35,7 +35,7 @@ public abstract class AbstractApiClient implements ApiClient {
this.privacy = profile.getPrivacy();
this.signature = profile.getSignature();
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
@ -140,9 +140,8 @@ public abstract class AbstractApiClient implements ApiClient {
byte[] secretKey = cipher.getSecretKey();
// 密钥进行非对称加密
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());

View File

@ -21,7 +21,7 @@ public class DefaultHttpProfile implements HttpProfile {
// 请求代理
private final Proxy proxy;
// 是否启用日志打印 默认true
private final boolean logEnabled;
private final LogLevel logLevel;
// 是否启用压缩
private final boolean compressionEnabled;
@ -31,13 +31,13 @@ public class DefaultHttpProfile implements HttpProfile {
this.connPool = builder.connPool;
this.headers = builder.headers;
this.proxy = builder.proxy;
this.logEnabled = builder.logEnabled;
this.logLevel = builder.logLevel;
this.compressionEnabled = builder.compressionEnabled;
}
@Override
public boolean logEnabled() {
return logEnabled;
public LogLevel logLevel() {
return logLevel;
}
@Override
@ -82,7 +82,7 @@ public class DefaultHttpProfile implements HttpProfile {
// 请求代理
private Proxy proxy;
// 是否启用日志打印
private boolean logEnabled = true;
private LogLevel logLevel = LogLevel.basic;
// 是否启用压缩
private boolean compressionEnabled = false;
@ -111,8 +111,8 @@ public class DefaultHttpProfile implements HttpProfile {
return this;
}
public Builder logEnabled(boolean logEnabled) {
this.logEnabled = logEnabled;
public Builder logLevel(LogLevel logLevel) {
this.logLevel = logLevel;
return this;
}

View File

@ -5,16 +5,22 @@ import com.czcb.scfs.api.core.util.Strings;
import org.slf4j.Logger;
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
* @since 2.0.0
*/
public class HttpLogger {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final boolean logEnabled;
private final LogLevel logLevel;
private final boolean logPrefix = false;
public HttpLogger(boolean logEnabled) {
this.logEnabled = logEnabled;
public HttpLogger(LogLevel logLevel) {
this.logLevel = logLevel;
}
/**
@ -24,23 +30,27 @@ public class HttpLogger {
* @param httpVersion http
*/
protected void logRequest(HttpRequest request, String httpVersion) {
if (!logEnabled) {
return;
String logPrefixText = logPrefix(request);
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) {
EncryptRequestBody body = (EncryptRequestBody) request.getRequestBody();
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getOriginalBody()));
logger.info("[{}] 请求加密报文:{}", request.getId(), Strings.toStr(body.getBody()));
EncryptRequestBody requestBody = (EncryptRequestBody) request.getRequestBody();
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) {
JsonRequestBody body = (JsonRequestBody) request.getRequestBody();
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getBody()));
JsonRequestBody requestBody = (JsonRequestBody) request.getRequestBody();
String bodyText = Strings.toStr(requestBody.getBody());
logger.info("{}请求报文:{}", logPrefixText, bodyText);
}
}
@ -53,18 +63,26 @@ public class HttpLogger {
* @param <T>
*/
protected <T> void logResponse(HttpRequest request, OriginalResponse originalResponse, HttpResponse<T> response, long duration) {
if (!logEnabled) {
return;
String logPrefixText = logPrefix(request);
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());
StringBuilder sb = new StringBuilder();
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()));
String requestId = originalResponse.getHttpHeaders().getHeader(REQUEST_ID);
logger.info("{}应答-服务端Request-Id:{}", logPrefixText, requestId);
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
*/
public void logResponseError(HttpRequest request, OriginalResponse originalResponse) {
logger.error("[{}] 响应:{} {}", request.getId(), originalResponse.getVersion(), originalResponse.getStatusCode());
StringBuilder sb = new StringBuilder();
originalResponse.getHttpHeaders().getHeaders().forEach((k, v) -> sb.append(k).append("=").append(v).append(";"));
logger.error("[{}] 响应头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
logger.error("[{}] 响应原始报文:{}", request.getId(), Strings.toStr((originalResponse.getBody())));
String logPrefixText = logPrefix(request);
logger.error("{}响应:{} {}", request.getId(), originalResponse.getVersion(), originalResponse.getStatusCode());
if (isFull(logLevel)) {
originalResponse.getHttpHeaders().getHeaders().forEach((k, v) -> logger.info("{}请求头:{}:{}", logPrefixText, k, v));
String body = Strings.toStr(originalResponse.getBody());
logger.error("{}响应原始报文:{}", logPrefixText, body);
}
}
public void logHttpStatus(OriginalResponse response) {
// TODO 打印状态码说明
public String httpReasonPhrase(OriginalResponse response) {
HttpStatus status = HttpStatus.resolve(response.getStatusCode());
if (Objects.isNull(status)) {
return "";
}
return status.getReasonPhrase();
}
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 "";
}
}

View File

@ -19,7 +19,7 @@ public interface HttpProfile {
*
* @return Boolean
*/
boolean logEnabled();
LogLevel logLevel();
/**
*

View File

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

View File

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

View File

@ -40,7 +40,7 @@ class ApiClientBuilderTest {
.build(),
new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()
@ -142,7 +142,7 @@ class ApiClientBuilderTest {
.port("1000")
.build())
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -16,7 +16,7 @@ class DefaultHttpProfileTest {
.headers(data)
.compressionEnabled(true)
.online(true)
.logEnabled(true)
.logLevel(LogLevel.basic)
.host("http://10.133.129.74:8761/")
.build();
@ -26,7 +26,7 @@ class DefaultHttpProfileTest {
Assertions.assertTrue(httpProfile.compressionEnabled());
Assertions.assertTrue(httpProfile.online());
Assertions.assertTrue(httpProfile.logEnabled());
Assertions.assertEquals(LogLevel.basic, httpProfile.logLevel());
}
@Test

View File

@ -51,7 +51,7 @@ class ApacheHttpclientProxyTest {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -53,7 +53,7 @@ class ApacheHttpclientTest {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(compressionEnabled)
.host("http://127.0.0.1:8888")
.build()

View File

@ -51,7 +51,7 @@ class ApacheHttpclientTestProxyTest {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -52,7 +52,7 @@ class ApacheHttpclientV2Test {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -52,7 +52,7 @@ class ApacheHttpclientV3Test {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -6,6 +6,7 @@ import com.czcb.scfs.api.core.Profile;
import com.czcb.scfs.api.core.cipher.*;
import com.czcb.scfs.api.core.http.ApiClientBuilder;
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.Nonce;
import com.czcb.scfs.api.core.util.Strings;
@ -52,7 +53,7 @@ public class MockResponse {
.appNo("100000")
.build(), new DefaultHttpProfile.Builder()
.online(false)
.logEnabled(true)
.logLevel(LogLevel.basic)
.compressionEnabled(false)
.host("http://127.0.0.1:8888")
.build()

View File

@ -37,7 +37,7 @@ public abstract class AbstractAutoConfiguration {
.online(getProperties().getOnline())
.host(getProperties().getHost())
.headers(getProperties().getHttpclient().getHeaders())
.logEnabled(getProperties().getHttpclient().getLogEnabled())
.logLevel(getProperties().getHttpclient().getLogLevel())
.compressionEnabled(getProperties().getHttpclient().getCompressionEnabled())
.proxy(proxy.build())
.connPool(connPool)

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.spring.boot.starter;
import com.czcb.scfs.api.core.cipher.StoreType;
import com.czcb.scfs.api.core.http.LogLevel;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashMap;
@ -160,9 +161,9 @@ public class ScfsApiGatewayProperties {
public static class Httpclient {
/**
* true
* basic
*/
private Boolean logEnabled = true;
private LogLevel logLevel = LogLevel.basic;
/**
* false
*/
@ -183,12 +184,12 @@ public class ScfsApiGatewayProperties {
*/
private Map<String, String> headers = new HashMap<>();
public Boolean getLogEnabled() {
return logEnabled;
public LogLevel getLogLevel() {
return logLevel;
}
public void setLogEnabled(Boolean logEnabled) {
this.logEnabled = logEnabled;
public void setLogLevel(LogLevel logLevel) {
this.logLevel = logLevel;
}
public Boolean getCompressionEnabled() {

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.spring.boot.starter;
import com.czcb.scfs.api.core.cipher.StoreType;
import com.czcb.scfs.api.core.http.LogLevel;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -65,15 +66,15 @@ class ScfsApiGatewayPropertiesTest {
httpclient.setConnPool(connPool);
httpclient.setCompressionEnabled(false);
httpclient.setLogEnabled(false);
httpclient.setLogLevel(LogLevel.full);
ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties();
properties.setHttpclient(httpclient);
Assertions.assertNotNull(properties.getHttpclient());
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}," +
"\"proxy\":{\"enabled\":true,\"host\":\"128.0.0.1\",\"port\":\"1000\",\"username\":\"name\",\"password\":\"123456\",\"scheme\":\"https\"}," +
"\"headers\":{\"aa\":\"123456\"}}")

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.spring.boot.starter;
import com.czcb.scfs.api.core.cipher.StoreType;
import com.czcb.scfs.api.core.http.LogLevel;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -42,7 +43,7 @@ class SmConfigurationTest {
connPool.setSocketTimeout(100);
httpclient.setConnPool(connPool);
httpclient.setCompressionEnabled(false);
httpclient.setLogEnabled(false);
httpclient.setLogLevel(LogLevel.basic);
properties.setHttpclient(httpclient);
ScfsApiGatewayProperties.Channel channel = new ScfsApiGatewayProperties.Channel();