request id

main
13009 2024-03-26 11:07:55 +08:00
parent 04ec5ee891
commit 92beab28c1
7 changed files with 69 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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