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