request id
parent
04ec5ee891
commit
92beab28c1
|
|
@ -5,7 +5,6 @@ import com.czcb.scfs.api.core.http.HttpHeaders;
|
|||
import com.czcb.scfs.api.core.http.HttpRequest;
|
||||
import com.czcb.scfs.api.core.http.OriginalResponse;
|
||||
import com.czcb.scfs.api.core.util.DateTimes;
|
||||
import com.czcb.scfs.api.core.util.Nonce;
|
||||
import com.czcb.scfs.api.core.util.Strings;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
@ -33,7 +32,7 @@ public class DefaultCredential implements Credential {
|
|||
}
|
||||
|
||||
private void addNecessityCustomizeHeaders(HttpRequest request) {
|
||||
request.getHttpHeaders().addHeader(NONCE, Nonce.ofNonce());
|
||||
request.getHttpHeaders().addHeader(NONCE, request.getId());
|
||||
request.getHttpHeaders().addHeader(TIMESTAMP, DateTimes.ofTimestamp());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.czcb.scfs.api.core.Profile;
|
|||
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.OriginalResponse;
|
||||
import com.czcb.scfs.api.core.util.Strings;
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ public final class DefaultValidator implements Validator {
|
|||
return httpCode < HTTP_OK || httpCode >= HTTP_MULT_CHOICE;
|
||||
}
|
||||
|
||||
private void validateTimestamp(OriginalResponse response) {
|
||||
private void validateTimestamp(HttpRequest request, OriginalResponse response) {
|
||||
try {
|
||||
String timestamp = response.getHttpHeaders().getHeader(TIMESTAMP);
|
||||
if (Strings.isEmpty(timestamp)) {
|
||||
|
|
@ -51,19 +52,19 @@ public final class DefaultValidator implements Validator {
|
|||
timestamp, response.getHttpHeaders().getHeader(REQUEST_ID)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
httpLogger.logResponseError(response);
|
||||
httpLogger.logResponseError(request, response);
|
||||
throw new TimestampException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(OriginalResponse response, Channel channel) {
|
||||
public void validate(HttpRequest request, OriginalResponse response, Channel channel) {
|
||||
if (isInvalidHttpCode(response.getStatusCode())) {
|
||||
httpLogger.logHttpStatus(response);
|
||||
}
|
||||
|
||||
// 校验时间戳
|
||||
validateTimestamp(response);
|
||||
validateTimestamp(request, response);
|
||||
|
||||
// 请求头包含 SecretKey 进行验签
|
||||
if (!headerContainsSecretKey(response)) {
|
||||
|
|
@ -80,7 +81,7 @@ public final class DefaultValidator implements Validator {
|
|||
}
|
||||
|
||||
if (!verifier.verify(null, message, signature)) {
|
||||
httpLogger.logResponseError(response);
|
||||
httpLogger.logResponseError(request, response);
|
||||
throw new ValidationException(String.format("响应校验失败, 签名校验未通过, Request-Id=%s",
|
||||
response.getHttpHeaders().getHeader(REQUEST_ID)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.czcb.scfs.api.core.cipher;
|
||||
|
||||
import com.czcb.scfs.api.core.Channel;
|
||||
import com.czcb.scfs.api.core.http.HttpRequest;
|
||||
import com.czcb.scfs.api.core.http.OriginalResponse;
|
||||
|
||||
/**
|
||||
|
|
@ -12,5 +13,5 @@ public interface Validator {
|
|||
/**
|
||||
* 验证返回是否合法
|
||||
*/
|
||||
void validate(OriginalResponse response, Channel channel);
|
||||
void validate(HttpRequest request, OriginalResponse response, Channel channel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,18 +68,19 @@ public abstract class AbstractApiClient implements ApiClient {
|
|||
// 实际调用
|
||||
originalResponse = doRemoteExecute(newRequest);
|
||||
} catch (Exception e) {
|
||||
httpLogger.logRemoteError(newRequest, e.getMessage());
|
||||
throw new ApiClientException(e);
|
||||
} finally {
|
||||
watch.stop();
|
||||
}
|
||||
|
||||
// 校验响应
|
||||
OriginalResponse resultfulResponse = validateResponse(originalResponse);
|
||||
OriginalResponse resultfulResponse = validateResponse(newRequest, originalResponse);
|
||||
|
||||
// 解析返回数据
|
||||
HttpResponse<T> httpResponse = assembleHttpResponse(resultfulResponse, responseClass);
|
||||
// 打印响应结果
|
||||
httpLogger.logResponse(originalResponse, httpResponse, watch.getLastTaskTimeMillis());
|
||||
httpLogger.logResponse(newRequest, originalResponse, httpResponse, watch.getLastTaskTimeMillis());
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +95,7 @@ public abstract class AbstractApiClient implements ApiClient {
|
|||
request = httpRequestEncrypt(request);
|
||||
// 组合请求数据
|
||||
HttpRequest.Builder builder = new HttpRequest.Builder()
|
||||
.id(request.getId())
|
||||
.url(fullUrlPattern(request))
|
||||
.httpMethod(request.getHttpMethod())
|
||||
.addHeader(AUTHORIZATION, getAuthorization(request))
|
||||
|
|
@ -172,8 +174,8 @@ public abstract class AbstractApiClient implements ApiClient {
|
|||
* @param originalResponse OriginalResponse
|
||||
* @return OriginalResponse
|
||||
*/
|
||||
private OriginalResponse validateResponse(OriginalResponse originalResponse) {
|
||||
validator.validate(originalResponse, getProfile().getChannel());
|
||||
private OriginalResponse validateResponse(HttpRequest request, OriginalResponse originalResponse) {
|
||||
validator.validate(request, originalResponse, getProfile().getChannel());
|
||||
return originalResponse;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,19 +28,19 @@ public class HttpLogger {
|
|||
return;
|
||||
}
|
||||
|
||||
logger.info("请求行:{} {} {}", request.getHttpMethod(), request.getUrl(), httpVersion);
|
||||
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("请求头:{}", Strings.removeSuffix(sb.toString(), ";"));
|
||||
logger.info("[{}] 请求头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
|
||||
|
||||
if (request.getRequestBody() instanceof EncryptRequestBody) {
|
||||
EncryptRequestBody body = (EncryptRequestBody) request.getRequestBody();
|
||||
logger.info("请求原始报文:{}", Strings.toStr(body.getOriginalBody()));
|
||||
logger.info("请求加密报文:{}", Strings.toStr(body.getBody()));
|
||||
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getOriginalBody()));
|
||||
logger.info("[{}] 请求加密报文:{}", request.getId(), Strings.toStr(body.getBody()));
|
||||
} else if (request.getRequestBody() instanceof JsonRequestBody) {
|
||||
JsonRequestBody body = (JsonRequestBody) request.getRequestBody();
|
||||
logger.info("请求原始报文:{}", Strings.toStr(body.getBody()));
|
||||
logger.info("[{}] 请求原始报文:{}", request.getId(), Strings.toStr(body.getBody()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,19 +52,19 @@ public class HttpLogger {
|
|||
* @param duration 请求耗时
|
||||
* @param <T> 返回类型
|
||||
*/
|
||||
protected <T> void logResponse(OriginalResponse originalResponse, HttpResponse<T> response, long duration) {
|
||||
protected <T> void logResponse(HttpRequest request, OriginalResponse originalResponse, HttpResponse<T> response, long duration) {
|
||||
if (!logEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("响应行:{} {}", originalResponse.getVersion(), originalResponse.getStatusCode());
|
||||
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("响应头:{}", Strings.removeSuffix(sb.toString(), ";"));
|
||||
logger.info("响应原始报文:{}", Strings.toStr(response.getOriginalBody()));
|
||||
logger.info("响应解密报文:{}", Json.toJson(response.getServiceResponse()));
|
||||
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("请求-响应耗时(毫秒):{}", duration);
|
||||
logger.info("[{}] 请求-响应耗时(毫秒):{}", request.getId(), duration);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,15 +72,19 @@ public class HttpLogger {
|
|||
*
|
||||
* @param originalResponse 响应数据
|
||||
*/
|
||||
public void logResponseError(OriginalResponse originalResponse) {
|
||||
logger.info("响应:{} {}", originalResponse.getVersion(), originalResponse.getStatusCode());
|
||||
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.info("响应头:{}", Strings.removeSuffix(sb.toString(), ";"));
|
||||
logger.info("响应原始报文:{}", Strings.toStr((originalResponse.getBody())));
|
||||
logger.error("[{}] 响应头:{}", request.getId(), Strings.removeSuffix(sb.toString(), ";"));
|
||||
logger.error("[{}] 响应原始报文:{}", request.getId(), Strings.toStr((originalResponse.getBody())));
|
||||
}
|
||||
|
||||
public void logHttpStatus(OriginalResponse response) {
|
||||
// TODO 打印状态码说明
|
||||
}
|
||||
|
||||
public void logRemoteError(HttpRequest newRequest, String message) {
|
||||
logger.error("[{}] 远程调用异常:{}", newRequest.getId(), message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package com.czcb.scfs.api.core.http;
|
||||
|
||||
import com.czcb.scfs.api.core.util.Nonce;
|
||||
import com.czcb.scfs.api.core.util.Strings;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
|
@ -14,6 +17,9 @@ import static java.util.Objects.requireNonNull;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
public class HttpRequest {
|
||||
// 请求Id
|
||||
private final String id;
|
||||
|
||||
// http 请求方法
|
||||
private final HttpMethod httpMethod;
|
||||
// 地址
|
||||
|
|
@ -27,6 +33,10 @@ public class HttpRequest {
|
|||
// 是否开启压缩
|
||||
private final boolean compression;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public HttpMethod getHttpMethod() {
|
||||
return httpMethod;
|
||||
}
|
||||
|
|
@ -53,6 +63,7 @@ public class HttpRequest {
|
|||
|
||||
public Builder newBuilder() {
|
||||
return new Builder()
|
||||
.id(this.id)
|
||||
.httpMethod(this.httpMethod)
|
||||
.url(this.url)
|
||||
.headers(this.httpHeaders)
|
||||
|
|
@ -62,6 +73,7 @@ public class HttpRequest {
|
|||
}
|
||||
|
||||
private HttpRequest(Builder builder) {
|
||||
this.id = builder.id;
|
||||
this.httpMethod = builder.httpMethod;
|
||||
this.url = builder.url;
|
||||
this.parameters = builder.parameters;
|
||||
|
|
@ -71,6 +83,7 @@ public class HttpRequest {
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
private String id;
|
||||
private HttpMethod httpMethod;
|
||||
private String url;
|
||||
private HttpHeaders headers = new HttpHeaders();
|
||||
|
|
@ -160,6 +173,17 @@ public class HttpRequest {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求id
|
||||
*
|
||||
* @param id id
|
||||
* @return Builder
|
||||
*/
|
||||
public Builder id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建HttpRequest
|
||||
*
|
||||
|
|
@ -169,6 +193,10 @@ public class HttpRequest {
|
|||
requireNonNull(this.httpMethod);
|
||||
requireNonNull(this.url);
|
||||
|
||||
if (Strings.isEmpty(this.id)) {
|
||||
this.id = Nonce.ofNonce();
|
||||
}
|
||||
|
||||
if (Objects.isNull(this.headers)) {
|
||||
this.headers = new HttpHeaders();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@
|
|||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.7.16</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue