- ApiTesterFilter: gw 호출 시 base-url 재조립 처리 추가 - admin 스펙 저장 시 실주소 고정 제거 - 재치환 유연성 확보
This commit is contained in:
@@ -29,10 +29,6 @@
|
||||
// (enricher 는 oauth·api_key 를 모두 apiKey-in-header 로 모델링하므로 scheme.type 만으로 구분 불가)
|
||||
var djbAuthType = '';
|
||||
|
||||
// 저장 스펙의 서버 자리표시자. 포탈이 제공 시점에 응답유형(sample/mock/gw)별 실주소로 치환한다.
|
||||
// (포탈 DjbTestbedSpecServerRewriter.SERVER_SENTINEL 과 동일 문자열 — 양쪽을 같이 바꿔야 한다)
|
||||
const SERVER_SENTINEL = 'http://swagger-server-url';
|
||||
|
||||
// ============================================================
|
||||
// 2. 유틸
|
||||
// ============================================================
|
||||
@@ -112,13 +108,7 @@
|
||||
// ============================================================
|
||||
// 3. OpenAPI 스펙 빌더 (state.data → OpenAPI 3.1 객체)
|
||||
// ============================================================
|
||||
/**
|
||||
* state.data → OpenAPI 3.1 객체.
|
||||
*
|
||||
* @param resolveHost true 면 응답유형별 실주소를 서버에 부착(편집기 미리보기·다운로드용),
|
||||
* false/생략이면 서버를 sentinel 로 남긴다(저장본 — 포탈이 제공 시점에 치환).
|
||||
*/
|
||||
function buildOpenApiSpec(resolveHost) {
|
||||
function buildOpenApiSpec() {
|
||||
const d = state.data;
|
||||
syncResponseExamplesFromSchema(); // 응답 예제 = 응답 정보(스키마·예제값) 파생 — 저장/미리보기 일관
|
||||
const spec = {
|
||||
@@ -201,23 +191,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 경로(op.path.value)에는 어댑터경로가 이미 baking 됨(백엔드 applyAutoRules). 서버에는 응답유형별 호스트만 붙인다.
|
||||
// - gw : djb.gateway.base-url (PortalProperty) → [gw호스트 + 어댑터경로 + 경로]
|
||||
// - mock : Mock Server URL(전체 URL) → [mock URL 그대로] (어댑터/오퍼레이션 경로 미부착)
|
||||
// - 그 외 : 호스트 없음 → [어댑터경로 + 경로]
|
||||
//
|
||||
// 단 이 실주소 부착은 "미리보기/다운로드" 표현에만 적용한다(resolveHost=true).
|
||||
// 저장본은 서버를 sentinel 로 남겨 환경 독립을 유지하고, 포탈이 제공 시점에 응답유형별 실주소로
|
||||
// 치환한다(DjbTestbedSpecServerRewriter). 저장본에 실주소를 굳히면 포탈의 재치환이 무력화되고
|
||||
// 저장 환경(dev)의 GW 주소가 다른 환경까지 따라간다.
|
||||
if (resolveHost) {
|
||||
var _resolved = resolveSpecServer();
|
||||
if (_resolved.host) spec.servers = [{ url: _resolved.host }];
|
||||
spec.paths[_resolved.path] = { [op.method.value.toLowerCase()]: operation };
|
||||
} else {
|
||||
spec.servers = [{ url: SERVER_SENTINEL }];
|
||||
spec.paths[op.path.value] = { [op.method.value.toLowerCase()]: operation };
|
||||
}
|
||||
// spec 의 서버는 응답유형과 무관하게 항상 GW 주소로 고정한다 — spec 은 "이 API 를 실제로 어디로
|
||||
// 호출하는가"의 공개 계약이고, 그 기준은 게이트웨이다. sample/mock 은 테스트베드 동작(포탈
|
||||
// ApiTesterFilter 가 응답유형에 따라 sampleResponse 반환 / mockUrl forward)에서만 갈린다.
|
||||
// 경로(op.path.value)에는 어댑터경로가 이미 baking 됨(백엔드 applyAutoRules).
|
||||
spec.servers = [{ url: gatewayAddress() }];
|
||||
spec.paths[op.path.value] = { [op.method.value.toLowerCase()]: operation };
|
||||
|
||||
// 보안 스킴
|
||||
d.securitySchemes.forEach(s => {
|
||||
@@ -989,22 +968,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 응답유형별 실주소 { host, path }. 편집기 미리보기·다운로드에서만 사용(저장본은 sentinel).
|
||||
// - gw : DJB_CTX.gwAddress + [어댑터경로 + 경로]
|
||||
// - mock : Mock Server URL 을 origin/path 로 분해 → 경로가 뒤에 덧붙지 않음
|
||||
// - 그 외 : 호스트 없음 + [어댑터경로 + 경로]
|
||||
function resolveSpecServer() {
|
||||
var d = state.data;
|
||||
var rt = (d.portal && d.portal.responseType) || 'sample';
|
||||
var path = d.operation.path.value;
|
||||
if (rt === 'gw') {
|
||||
return { host: (window.DJB_CTX && window.DJB_CTX.gwAddress) || 'http://127.0.0.1:39310', path: path };
|
||||
}
|
||||
if (rt === 'mock') {
|
||||
var mk = splitFullUrl((d.portal && d.portal.mockUrl) || '');
|
||||
return { host: mk.origin, path: mk.path };
|
||||
}
|
||||
return { host: '', path: path };
|
||||
// spec servers 에 넣을 게이트웨이 주소(단일 기준). 응답유형과 무관하게 항상 이 값을 쓴다.
|
||||
function gatewayAddress() {
|
||||
return (window.DJB_CTX && window.DJB_CTX.gwAddress) || 'http://127.0.0.1:39310';
|
||||
}
|
||||
|
||||
// 전체 URL → { origin, path }. Mock Server URL 을 서버+경로로 분해(경로를 별도로 덧붙이지 않기 위함).
|
||||
@@ -1129,8 +1095,7 @@
|
||||
}
|
||||
|
||||
function mountSwagger() {
|
||||
// 미리보기는 실주소로 — sentinel 이 가짜 주소로 보이면 안 된다.
|
||||
const spec = buildOpenApiSpec(true);
|
||||
const spec = buildOpenApiSpec();
|
||||
swaggerInstance = SwaggerUIBundle({
|
||||
spec: spec,
|
||||
domNode: $('#preview-swagger'),
|
||||
@@ -1148,7 +1113,7 @@
|
||||
|
||||
function updateMonacoFromState() {
|
||||
if (!monacoReady) return;
|
||||
const spec = buildOpenApiSpec(true); // YAML 미리보기도 실주소 표시
|
||||
const spec = buildOpenApiSpec();
|
||||
const yaml = jsyaml.dump(spec, { noRefs: true, lineWidth: 120 });
|
||||
if (monacoEditor.getValue() !== yaml) monacoEditor.setValue(yaml);
|
||||
}
|
||||
@@ -1647,7 +1612,7 @@
|
||||
// 16. Export
|
||||
// ============================================================
|
||||
function downloadSpec(format) {
|
||||
const spec = buildOpenApiSpec(true); // 편집기 다운로드는 실주소 산출물
|
||||
const spec = buildOpenApiSpec();
|
||||
if (format === 'yaml') { doDownload(jsyaml.dump(spec, { noRefs: true }), 'text/yaml', 'yaml'); return; }
|
||||
if (format === 'json') { doDownload(JSON.stringify(spec, null, 2), 'application/json', 'json'); return; }
|
||||
// html — 폐쇄망 자립: 벤더 swagger css/js 를 fetch 해 인라인
|
||||
@@ -2050,7 +2015,6 @@
|
||||
function saveSpec(temp) {
|
||||
var ctx = window.DJB_CTX || {};
|
||||
if (!ctx.saveUrl || !ctx.eaiSvcName) { toast('저장 대상이 없습니다', 'error'); return; }
|
||||
// 저장본은 sentinel 유지 — 실주소는 포탈이 제공 시점에 응답유형별로 치환한다.
|
||||
var spec = buildOpenApiSpec();
|
||||
var d = state.data;
|
||||
var reqEx = (d.examples && d.examples.request && d.examples.request[d.requestBody && d.requestBody.mediaType || 'application/json'] || {}).default || '';
|
||||
|
||||
Reference in New Issue
Block a user