@@ -43,6 +43,7 @@
|
||||
$('#sendBy').text(data.sendBy || '');
|
||||
$('#sentAt').text(data.sentAt || '');
|
||||
$('#signature').text(data.signature || '');
|
||||
$('#userSecret').text(data.userSecret || '');
|
||||
$('#errorMessage').text(data.errorMessage || '');
|
||||
$('#payload').text(data.payload || '');
|
||||
$('#responseBody').text(data.responseBody || '');
|
||||
@@ -116,7 +117,9 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Signature</th>
|
||||
<td colspan="3"><span id="signature"></span></td>
|
||||
<td><span id="signature"></span></td>
|
||||
<th>User Secret</th>
|
||||
<td><span id="userSecret"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Payload</th>
|
||||
|
||||
@@ -71,6 +71,9 @@ public class WebhookSendLog {
|
||||
|
||||
@Column(name = "SEND_BY", length = 100)
|
||||
private String sendBy;
|
||||
|
||||
@Column(name = "USER_SECRET")
|
||||
private String userSecret;
|
||||
|
||||
/* Boolean 편의 메서드 */
|
||||
public void setSuccess(Boolean success) {
|
||||
|
||||
@@ -24,6 +24,7 @@ public class WebhookSendLogUI {
|
||||
|
||||
private String payload;
|
||||
private String signature;
|
||||
private String userSecret;
|
||||
|
||||
private Integer statusCode;
|
||||
private String responseBody;
|
||||
|
||||
@@ -12,5 +12,6 @@ public class WebhookSendRequest {
|
||||
private String eventType;
|
||||
private String secret;
|
||||
private String reverseProxyPath;
|
||||
private String userSecret;
|
||||
private Object data;
|
||||
}
|
||||
+1
@@ -157,6 +157,7 @@ public class WebhookSendLogManService extends BaseService {
|
||||
ui.setProxyUrl(e.getProxyUrl());
|
||||
ui.setPayload(e.getPayload());
|
||||
ui.setSignature(e.getSignature());
|
||||
ui.setUserSecret(e.getUserSecret());
|
||||
ui.setStatusCode(e.getStatusCode());
|
||||
ui.setResponseBody(e.getResponseBody());
|
||||
ui.setSuccess(e.getSuccess());
|
||||
|
||||
@@ -67,7 +67,7 @@ public class WebhookService {
|
||||
String reverseProxyUrl = monitoringContext.getProperty(MonitoringContext.RMS_WEBHOOK_REVERSE_PROXY_URL);
|
||||
|
||||
List<Tuple> tuples = new JPAQueryFactory(entityManager)
|
||||
.select(req.orgId, req.targetUrl, req.secret, org.reverseProxyPath, api.id.apiId)
|
||||
.select(req.orgId, req.targetUrl, req.secret, req.userSecret, org.reverseProxyPath, api.id.apiId)
|
||||
.from(req)
|
||||
.join(evt).on(req.id.eq(evt.id.webhookReqId))
|
||||
.join(api).on(req.id.eq(api.id.webhookReqId))
|
||||
@@ -84,8 +84,9 @@ public class WebhookService {
|
||||
WebhookSendRequest wr = new WebhookSendRequest();
|
||||
wr.setOrgId(t.get(req.orgId));
|
||||
wr.setTargetUrl(t.get(req.targetUrl));
|
||||
wr.setProxyUrl(this.getProxyUrl(reverseProxyUrl, t.get(org.reverseProxyPath), t.get(req.targetUrl)));
|
||||
wr.setProxyUrl(this.getProxyUrl(reverseProxyUrl, t.get(org.reverseProxyPath)));
|
||||
wr.setSecret(t.get(req.secret));
|
||||
wr.setUserSecret(t.get(req.userSecret));
|
||||
wr.setEventType(event);
|
||||
wr.setData(new ArrayList<String>());
|
||||
return wr;
|
||||
@@ -104,17 +105,17 @@ public class WebhookService {
|
||||
}
|
||||
|
||||
//reverse proxy 서버로 발송하기 위한 url 만든다
|
||||
private String getProxyUrl(String proxyUrl, String path, String targetUrl) {
|
||||
private String getProxyUrl(String proxyUrl, String path) {
|
||||
String base = stripTrailingSlash(proxyUrl);
|
||||
String normalizedPath = stripSlashes(path);
|
||||
// scheme://host[:port] 부분만 제거하고 이후 path/query/fragment는 그대로 유지
|
||||
String targetPath = targetUrl.replaceFirst("^[a-zA-Z][a-zA-Z0-9+.-]*://[^/]+", "");
|
||||
// // scheme://host[:port] 부분만 제거하고 이후 path/query/fragment는 그대로 유지
|
||||
// String targetPath = targetUrl.replaceFirst("^[a-zA-Z][a-zA-Z0-9+.-]*://[^/]+", "");
|
||||
|
||||
StringBuilder url = new StringBuilder(base);
|
||||
if (!normalizedPath.isEmpty()) {
|
||||
url.append('/').append(normalizedPath);
|
||||
}
|
||||
url.append(targetPath);
|
||||
// url.append(targetPath);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
@@ -152,7 +153,9 @@ public class WebhookService {
|
||||
String targetUrl = req.getTargetUrl();
|
||||
String proxyUrl = req.getProxyUrl();
|
||||
String secret = req.getSecret();
|
||||
String userSecret = req.getUserSecret();
|
||||
String eventType = req.getEventType();
|
||||
String message = getMessage(eventType);
|
||||
Object data = req.getData();
|
||||
|
||||
WebhookSendLog sendLog = new WebhookSendLog();
|
||||
@@ -160,11 +163,12 @@ public class WebhookService {
|
||||
sendLog.setTargetUrl(targetUrl);
|
||||
sendLog.setProxyUrl(proxyUrl);
|
||||
sendLog.setEventType(eventType);
|
||||
sendLog.setUserSecret(userSecret);
|
||||
sendLog.setSendBy(ContainerUtil.getInstanceName());
|
||||
|
||||
try {
|
||||
// 1. Payload 생성
|
||||
WebhookPayload webhookPayload = WebhookPayload.of(eventType, data);
|
||||
WebhookPayload webhookPayload = WebhookPayload.of(eventType, message, data);
|
||||
String payloadJson = objectMapper.writeValueAsString(webhookPayload);
|
||||
sendLog.setPayload(payloadJson);
|
||||
|
||||
@@ -175,9 +179,10 @@ public class WebhookService {
|
||||
// 3. HTTP 요청 헤더 구성
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("X-Webhook-Signature", "sha256=" + signature);
|
||||
headers.set("X-Webhook-Event", eventType);
|
||||
headers.set("X-Webhook-Timestamp", String.valueOf(webhookPayload.getTimestamp()));
|
||||
headers.set("x-webhook-signature", "sha256=" + signature);
|
||||
headers.set("x-webhook-event", eventType);
|
||||
headers.set("x-webhook-secret", userSecret);
|
||||
headers.set("x-webhook-timestamp", String.valueOf(webhookPayload.getTimestamp()));
|
||||
|
||||
// 4. 발송 (재시도 포함)
|
||||
int retryCount = monitoringContext.getIntProperty(MonitoringContext.RMS_WEBHOOK_RETRY_COUNT, DEFAULT_RETRY_COUNT);
|
||||
@@ -213,7 +218,18 @@ public class WebhookService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String getMessage(String event) {
|
||||
switch (event) {
|
||||
case "CHECK_START": return "API 서비스 점검이 시작되었습니다"; //점검
|
||||
case "CHECK_END": return "API 서비스 점검이 종료되었습니다"; //정상
|
||||
case "ERROR_START": return "API 서비스 장애가 발생하였습니다"; //장애
|
||||
case "ERROR_END": return "API 서비스 장애가 복구되었습니다"; //정상
|
||||
case "DELAY_START": return "API 서비스 지연이 발생하였습니다"; //지연
|
||||
case "DELAY_END": return "API 서비스 지연이 복구되었습니다"; //정상
|
||||
default:
|
||||
return "Webhook 메세지";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 재시도 포함 HTTP 발송
|
||||
|
||||
Reference in New Issue
Block a user