package com.vincent.rsf.httpaudit.web;
|
|
import com.vincent.rsf.httpaudit.model.HttpAuditDecision;
|
import com.vincent.rsf.httpaudit.service.HttpAuditOutboundRecorder;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.http.HttpRequest;
|
import org.springframework.http.client.ClientHttpRequestExecution;
|
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
import org.springframework.http.client.ClientHttpResponse;
|
import org.springframework.util.StreamUtils;
|
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
|
/**
|
* RestTemplate 出站审计
|
*/
|
@Slf4j
|
@RequiredArgsConstructor
|
public class OutboundHttpAuditInterceptor implements ClientHttpRequestInterceptor {
|
|
private static final String FN_REST = "HTTP出站(RestTemplate)";
|
|
private final HttpAuditOutboundRecorder outboundRecorder;
|
|
@Override
|
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
if (!outboundRecorder.isAuditEnabled()) {
|
return execution.execute(request, body);
|
}
|
String url = request.getURI().toString();
|
String method = request.getMethod().name();
|
String reqText = body == null || body.length == 0 ? "" : new String(body, StandardCharsets.UTF_8);
|
HttpAuditDecision dec = outboundRecorder.decideOutbound(url, method, reqText);
|
long t0 = System.currentTimeMillis();
|
ClientHttpResponse raw;
|
try {
|
raw = execution.execute(request, body);
|
} catch (IOException e) {
|
outboundRecorder.saveOutbound(FN_REST, url, method, reqText, dec, null, null, t0, e);
|
throw e;
|
}
|
byte[] respBytes;
|
try {
|
respBytes = StreamUtils.copyToByteArray(raw.getBody());
|
} catch (IOException e) {
|
outboundRecorder.saveOutbound(FN_REST, url, method, reqText, dec, raw.getRawStatusCode(), null, t0, e);
|
throw e;
|
}
|
if (!dec.isAudit()) {
|
return new CopiedBodyClientHttpResponse(raw, respBytes);
|
}
|
String resText = new String(respBytes, StandardCharsets.UTF_8);
|
outboundRecorder.saveOutbound(FN_REST, url, method, reqText, dec, raw.getRawStatusCode(), resText, t0, null);
|
return new CopiedBodyClientHttpResponse(raw, respBytes);
|
}
|
|
private static class CopiedBodyClientHttpResponse implements ClientHttpResponse {
|
|
private final ClientHttpResponse delegate;
|
private final byte[] body;
|
|
CopiedBodyClientHttpResponse(ClientHttpResponse delegate, byte[] body) {
|
this.delegate = delegate;
|
this.body = body != null ? body : new byte[0];
|
}
|
|
@Override
|
public org.springframework.http.HttpStatus getStatusCode() throws IOException {
|
return delegate.getStatusCode();
|
}
|
|
@Override
|
public int getRawStatusCode() throws IOException {
|
return delegate.getRawStatusCode();
|
}
|
|
@Override
|
public String getStatusText() throws IOException {
|
return delegate.getStatusText();
|
}
|
|
@Override
|
public void close() {
|
delegate.close();
|
}
|
|
@Override
|
public org.springframework.http.HttpHeaders getHeaders() {
|
return delegate.getHeaders();
|
}
|
|
@Override
|
public java.io.InputStream getBody() throws IOException {
|
return new java.io.ByteArrayInputStream(body);
|
}
|
}
|
}
|