Webhook URL 형식 검증 로직 분리 및 재사용성 개선:
- WebhookUrlValidator 추가: URL 형식 검증 전담 - Service/Controller에서 공통 Validator 활용하도록 수정
This commit is contained in:
@@ -11,6 +11,7 @@ import com.eactive.apim.portal.djb.webhook.dto.WebhookDTO;
|
||||
import com.eactive.apim.portal.djb.webhook.dto.WebhookRegistrationDTO;
|
||||
import com.eactive.apim.portal.djb.webhook.service.WebhookEventTypeProvider;
|
||||
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
||||
import com.eactive.apim.portal.djb.webhook.service.WebhookUrlValidator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -375,10 +376,9 @@ public class WebhookController {
|
||||
|
||||
private void validateStep1(WebhookRegistrationDTO dto, BindingResult bindingResult) {
|
||||
String url = dto.getTargetUrl() == null ? "" : dto.getTargetUrl().trim();
|
||||
if (!bindingResult.hasFieldErrors("targetUrl")
|
||||
&& !url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
if (!bindingResult.hasFieldErrors("targetUrl") && !WebhookUrlValidator.isValid(url)) {
|
||||
bindingResult.rejectValue("targetUrl", "invalid.url",
|
||||
"URL은 http:// 또는 https:// 로 시작해야 합니다.");
|
||||
"올바른 URL 형식이 아닙니다. http:// 또는 https:// 로 시작하는 전체 주소를 입력해주세요.");
|
||||
}
|
||||
if (dto.getEventTypes() == null || dto.getEventTypes().isEmpty()) {
|
||||
bindingResult.rejectValue("eventTypes", "empty.eventTypes",
|
||||
|
||||
@@ -170,9 +170,8 @@ public class WebhookService {
|
||||
}
|
||||
|
||||
private void validate(WebhookRegistrationDTO dto) {
|
||||
String url = dto.getTargetUrl() == null ? "" : dto.getTargetUrl().trim();
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
throw new IllegalArgumentException("URL은 http:// 또는 https:// 로 시작해야 합니다.");
|
||||
if (!WebhookUrlValidator.isValid(dto.getTargetUrl())) {
|
||||
throw new IllegalArgumentException("올바른 URL 형식이 아닙니다. http:// 또는 https:// 로 시작하는 전체 주소를 입력해주세요.");
|
||||
}
|
||||
if (dto.getEventTypes() == null || dto.getEventTypes().isEmpty()) {
|
||||
throw new IllegalArgumentException("EventType을 1개 이상 선택해주세요.");
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.eactive.apim.portal.djb.webhook.service;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Webhook 수신 URL 형식 검증. 컨트롤러(필드 에러 표시)와 서비스(방어적 재검증) 양쪽에서 공용으로 쓴다.
|
||||
*
|
||||
* http/https 스킴 + host 존재까지 확인한다("http://" 만 있고 host 가 없는 값 등을 차단).
|
||||
* 순수 문법 검증만 하며, 실제 도달 가능성(DNS/네트워크)은 검사하지 않는다.
|
||||
*/
|
||||
public final class WebhookUrlValidator {
|
||||
|
||||
private WebhookUrlValidator() {
|
||||
}
|
||||
|
||||
public static boolean isValid(String url) {
|
||||
if (url == null || url.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
URI uri = new URI(url.trim());
|
||||
String scheme = uri.getScheme();
|
||||
return ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme))
|
||||
&& uri.getHost() != null && !uri.getHost().isEmpty();
|
||||
} catch (URISyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25733,29 +25733,31 @@ input[type=checkbox]:checked + .custom-checkbox {
|
||||
padding: 24px 16px 60px;
|
||||
font-family: "Spoqa Han Sans Neo", "Noto Sans CJK KR", sans-serif;
|
||||
}
|
||||
.webhook-container .field-help {
|
||||
|
||||
.step1-wrap .field-help {
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.webhook-container .field-help-red {
|
||||
.step1-wrap .field-help-red {
|
||||
color: #f4253c;
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
font-weight: 500;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.webhook-container .field-help-red {
|
||||
.step1-wrap .field-help-red {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
.webhook-container .field-error,
|
||||
.webhook-container .webhook-field-error {
|
||||
.step1-wrap .field-error,
|
||||
.step1-wrap .webhook-field-error {
|
||||
color: #f4253c;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.webhook-container .req {
|
||||
.step1-wrap .req {
|
||||
color: #f4253c;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -14,7 +14,12 @@ $wh-bg-soft: #f9f9f9;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px 60px;
|
||||
font-family: 'Spoqa Han Sans Neo', 'Noto Sans CJK KR', sans-serif;
|
||||
}
|
||||
|
||||
// 실제 페이지 마크업은 .webhook-container 가 아닌 .step1-wrap 으로 감싸여 있어
|
||||
// (webhookRegisterStep1/webhookModifyStep1/webhookList 공통) 여기로 스코프한다.
|
||||
// 위 .webhook-container 블록은 미사용이라 색상 규칙이 전혀 적용되지 않았었다.
|
||||
.step1-wrap {
|
||||
.field-help {
|
||||
color: $wh-muted;
|
||||
font-size: 13px;
|
||||
@@ -36,6 +41,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
.webhook-field-error {
|
||||
color: $wh-danger;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user