feat: add Glow HTTP tool integration sample
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 14s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 14s
This commit is contained in:
@@ -0,0 +1,124 @@
|
|||||||
|
package io.shinhanlife.dap.lib.integration.http.component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.shinhanlife.dap.lib.config.GlowCommunicationProperties;
|
||||||
|
import io.shinhanlife.dap.lib.mcp.McpRequestHeaderContext;
|
||||||
|
import io.shinhanlife.dap.lib.mcp.McpRequestHeaders;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.component.GlowHttpComponent;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpBody;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpHeader;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpTransfer;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tool Pod outbound HTTP component modelled after the ShinhanLife HTTP component.
|
||||||
|
* It resolves an API domain from configuration and delegates the assembled HttpTransfer to Glow.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AxhubHttpComponent {
|
||||||
|
|
||||||
|
private static final String ANONYMOUS_REQUEST = "AXHUB-TOOL";
|
||||||
|
|
||||||
|
private final GlowHttpComponent http;
|
||||||
|
private final ObjectMapper json;
|
||||||
|
private final GlowCommunicationProperties communicationProperties;
|
||||||
|
private final AxhubHttpProperties properties;
|
||||||
|
|
||||||
|
public <T, R> R call(AxhubHttpDomain domain, String uri, T inputDto, Class<R> responseBodyClass) {
|
||||||
|
return call(domain, uri, inputDto, responseBodyClass, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T, R> R call(AxhubHttpDomain domain, String uri, T inputDto, Class<R> responseBodyClass, int timeout) {
|
||||||
|
if (uri == null || uri.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("URI is required.");
|
||||||
|
}
|
||||||
|
AxhubHttpProperties.ApiDefinition api = resolveApi(domain);
|
||||||
|
HttpHeader header = createHeader(api, timeout);
|
||||||
|
String requestUri = joinPath(api.path(), uri);
|
||||||
|
HttpTransfer<T> request = HttpTransfer.<T>http()
|
||||||
|
.header(header)
|
||||||
|
.domain(api.domain())
|
||||||
|
.uri(requestUri)
|
||||||
|
.method(api.method())
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.responseEntity(responseBodyClass)
|
||||||
|
.body(inputDto)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.info("[AxhubHttpComponent] Glow HTTP call. domain={}, method={}, uri={}",
|
||||||
|
domain.getCode(), api.method(), requestUri);
|
||||||
|
ResponseEntity<HttpBody> response = http.sync(request);
|
||||||
|
return convertResponse(response.getBody(), responseBodyClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience method for APIs configured as internal business Pods. */
|
||||||
|
public <T, R> R callBizPod(AxhubHttpDomain domain, String uri, T inputDto, Class<R> responseBodyClass) {
|
||||||
|
AxhubHttpProperties.ApiDefinition api = resolveApi(domain);
|
||||||
|
if (!api.bizPod()) {
|
||||||
|
throw new IllegalArgumentException("Configured API is not a business Pod: " + domain.getCode());
|
||||||
|
}
|
||||||
|
return call(domain, uri, inputDto, responseBodyClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AxhubHttpProperties.ApiDefinition resolveApi(AxhubHttpDomain domain) {
|
||||||
|
return properties.getApiList().stream()
|
||||||
|
.filter(api -> domain.getCode().equals(api.name()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("No HTTP API configuration for domain: " + domain.getCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpHeader createHeader(AxhubHttpProperties.ApiDefinition api, int timeout) {
|
||||||
|
HttpHeader header = new HttpHeader();
|
||||||
|
if (api.bizPod()) {
|
||||||
|
header.set("X-POD-TO-POD", "true");
|
||||||
|
}
|
||||||
|
McpRequestHeaders inbound = McpRequestHeaderContext.current();
|
||||||
|
if (inbound == null) {
|
||||||
|
header.set("X-ANONYMOUS-REQ", ANONYMOUS_REQUEST);
|
||||||
|
} else {
|
||||||
|
putIfPresent(header, "trace-id", inbound.traceId());
|
||||||
|
putIfPresent(header, "request-id", inbound.requestId());
|
||||||
|
putIfPresent(header, "X-USER-ID", inbound.encryptedEmployeeId());
|
||||||
|
}
|
||||||
|
header.setReadTimeout(timeout == 0 ? defaultReadTimeout() : timeout);
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int defaultReadTimeout() {
|
||||||
|
return communicationProperties == null || communicationProperties.getHttp() == null
|
||||||
|
? 0 : communicationProperties.getHttp().getReadTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <R> R convertResponse(HttpBody responseBody, Class<R> responseBodyClass) {
|
||||||
|
String content = responseBody == null ? null : responseBody.content();
|
||||||
|
if (responseBodyClass == String.class) {
|
||||||
|
return responseBodyClass.cast(content);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return json.readValue(content, responseBodyClass);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new IllegalStateException("Failed to convert HTTP response to " + responseBodyClass.getSimpleName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putIfPresent(HttpHeader header, String name, String value) {
|
||||||
|
if (value != null && !value.isBlank()) {
|
||||||
|
header.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String joinPath(String basePath, String uri) {
|
||||||
|
String left = basePath == null ? "" : basePath.replaceAll("/+$", "");
|
||||||
|
String right = uri.startsWith("/") ? uri : "/" + uri;
|
||||||
|
return left + right;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package io.shinhanlife.dap.lib.integration.http.component;
|
||||||
|
|
||||||
|
/** Registered outbound HTTP API domains. Add a domain only after its endpoint is configured. */
|
||||||
|
public enum AxhubHttpDomain {
|
||||||
|
SAMPLE("sample");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
AxhubHttpDomain(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package io.shinhanlife.dap.lib.integration.http.component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/** Domain-to-endpoint configuration for outbound Tool HTTP calls. */
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "axhub.http")
|
||||||
|
public class AxhubHttpProperties {
|
||||||
|
|
||||||
|
private List<ApiDefinition> apiList = new ArrayList<>();
|
||||||
|
|
||||||
|
public record ApiDefinition(String name, String domain, String path, HttpMethod method, boolean bizPod) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package io.shinhanlife.glow.communication;
|
||||||
|
|
||||||
|
/** Minimal Glow communication contract used by the temporary compatibility layer. */
|
||||||
|
public interface ICommunication<I, O> {
|
||||||
|
O sync(I request);
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package io.shinhanlife.glow.communication.module.http.component;
|
||||||
|
|
||||||
|
import io.shinhanlife.glow.communication.ICommunication;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpBody;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpHeader;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.dto.HttpTransfer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary compatibility implementation of the internal Glow HTTP component.
|
||||||
|
* Replace this class with the official Glow HTTP JAR when it is supplied.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class GlowHttpComponent implements ICommunication<HttpTransfer<?>, ResponseEntity<HttpBody>> {
|
||||||
|
|
||||||
|
private final RestClient restClient;
|
||||||
|
|
||||||
|
public GlowHttpComponent(RestClient.Builder restClientBuilder) {
|
||||||
|
this.restClient = restClientBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<HttpBody> sync(HttpTransfer<?> request) {
|
||||||
|
if (request == null || request.getHeader() == null || request.getMethod() == null
|
||||||
|
|| !StringUtils.hasText(request.getDomain())) {
|
||||||
|
throw new IllegalArgumentException("Glow HTTP request header, domain, and method are required.");
|
||||||
|
}
|
||||||
|
if (HttpMethod.GET.equals(request.getMethod())) {
|
||||||
|
return get(request);
|
||||||
|
}
|
||||||
|
if (HttpMethod.POST.equals(request.getMethod())) {
|
||||||
|
return post(request);
|
||||||
|
}
|
||||||
|
if (HttpMethod.PUT.equals(request.getMethod())) {
|
||||||
|
return put(request);
|
||||||
|
}
|
||||||
|
if (HttpMethod.DELETE.equals(request.getMethod())) {
|
||||||
|
return delete(request);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported HTTP method: " + request.getMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<HttpBody> get(HttpTransfer<?> request) {
|
||||||
|
return toHttpBody(restClient.get().uri(buildUri(request, true))
|
||||||
|
.headers(headers -> applyHeaders(headers, request.getHeader()))
|
||||||
|
.retrieve().toEntity(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<HttpBody> post(HttpTransfer<?> request) {
|
||||||
|
return toHttpBody(restClient.post().uri(buildUri(request, false))
|
||||||
|
.contentType(contentType(request)).headers(headers -> applyHeaders(headers, request.getHeader()))
|
||||||
|
.body(request.getBody()).retrieve().toEntity(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<HttpBody> put(HttpTransfer<?> request) {
|
||||||
|
return toHttpBody(restClient.put().uri(buildUri(request, false))
|
||||||
|
.contentType(contentType(request)).headers(headers -> applyHeaders(headers, request.getHeader()))
|
||||||
|
.body(request.getBody()).retrieve().toEntity(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<HttpBody> delete(HttpTransfer<?> request) {
|
||||||
|
return toHttpBody(restClient.delete().uri(buildUri(request, true))
|
||||||
|
.headers(headers -> applyHeaders(headers, request.getHeader()))
|
||||||
|
.retrieve().toEntity(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildUri(HttpTransfer<?> request, boolean includeQueryParameters) {
|
||||||
|
String uri = request.getDomain() + (request.getUri() == null ? "" : request.getUri());
|
||||||
|
if (!includeQueryParameters || !(request.getBody() instanceof Map<?, ?> parameters)) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(uri);
|
||||||
|
parameters.forEach((key, value) -> { if (key != null && value != null) builder.queryParam(String.valueOf(key), value); });
|
||||||
|
return builder.build().encode().toUriString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MediaType contentType(HttpTransfer<?> request) {
|
||||||
|
return request.getContentType() == null ? MediaType.APPLICATION_JSON : request.getContentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyHeaders(HttpHeaders target, HttpHeader source) {
|
||||||
|
target.setAccept(List.of(MediaType.APPLICATION_JSON));
|
||||||
|
source.getValues().forEach((name, value) -> { if (StringUtils.hasText(name) && StringUtils.hasText(value)) target.set(name, value); });
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<HttpBody> toHttpBody(ResponseEntity<String> response) {
|
||||||
|
return new ResponseEntity<>(new HttpBody(response.getBody()), response.getHeaders(), response.getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.shinhanlife.glow.communication.module.http.dto;
|
||||||
|
|
||||||
|
/** Raw body returned by the Glow HTTP transport. */
|
||||||
|
public record HttpBody(String content) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package io.shinhanlife.glow.communication.module.http.dto;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/** Glow HTTP request headers and timeout metadata. */
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class HttpHeader {
|
||||||
|
private Map<String, String> values = new LinkedHashMap<>();
|
||||||
|
private int readTimeout;
|
||||||
|
|
||||||
|
public void set(String name, String value) {
|
||||||
|
values.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.shinhanlife.glow.communication.module.http.dto;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
|
/** Glow HTTP request envelope. Use HttpTransfer.http() to build a request. */
|
||||||
|
@Getter
|
||||||
|
@Builder(builderMethodName = "http")
|
||||||
|
public class HttpTransfer<T> {
|
||||||
|
private final HttpHeader header;
|
||||||
|
private final String domain;
|
||||||
|
private final String uri;
|
||||||
|
private final HttpMethod method;
|
||||||
|
private final MediaType contentType;
|
||||||
|
private final Class<?> responseEntity;
|
||||||
|
private final T body;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package io.shinhanlife.dap.lib.integration.http.component;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||||
|
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.shinhanlife.dap.lib.config.GlowCommunicationProperties;
|
||||||
|
import io.shinhanlife.glow.communication.module.http.component.GlowHttpComponent;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.test.web.client.MockRestServiceServer;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
|
class AxhubHttpComponentTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void callResolvesDomainBuildsGlowTransferAndDeserializesJsonResponse() {
|
||||||
|
RestClient.Builder builder = RestClient.builder();
|
||||||
|
MockRestServiceServer server = MockRestServiceServer.bindTo(builder).build();
|
||||||
|
GlowHttpComponent glowHttpComponent = new GlowHttpComponent(builder);
|
||||||
|
AxhubHttpProperties properties = new AxhubHttpProperties();
|
||||||
|
properties.setApiList(List.of(new AxhubHttpProperties.ApiDefinition(
|
||||||
|
"sample", "https://api.example.test", "/v1", HttpMethod.GET, false)));
|
||||||
|
AxhubHttpComponent component = new AxhubHttpComponent(
|
||||||
|
glowHttpComponent, new ObjectMapper(), new GlowCommunicationProperties(), properties);
|
||||||
|
|
||||||
|
server.expect(requestTo("https://api.example.test/v1/status"))
|
||||||
|
.andExpect(header("X-ANONYMOUS-REQ", "AXHUB-TOOL"))
|
||||||
|
.andRespond(withSuccess("{\"status\":\"OK\"}", APPLICATION_JSON));
|
||||||
|
|
||||||
|
SampleResponse response = component.call(AxhubHttpDomain.SAMPLE, "/status", null, SampleResponse.class);
|
||||||
|
|
||||||
|
assertThat(response.status()).isEqualTo("OK");
|
||||||
|
server.verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
record SampleResponse(String status) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package io.shinhanlife.dap.mcc.biz.smp.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
/** Tool response for the HTTP integration sample. */
|
||||||
|
public record SampleHttpStatusResponse(
|
||||||
|
@Schema(description = "External API processing status", example = "OK") String status,
|
||||||
|
@Schema(description = "External API response message", example = "Sample API is available") String message) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package io.shinhanlife.dap.mcc.biz.smp.usecase;
|
||||||
|
|
||||||
|
import io.shinhanlife.dap.lib.annotation.ToolHint;
|
||||||
|
import io.shinhanlife.dap.mcc.biz.smp.dto.SampleHttpStatusResponse;
|
||||||
|
import org.springaicommunity.mcp.annotation.McpTool;
|
||||||
|
|
||||||
|
/** Sample Tool that demonstrates a configured HTTP API integration. */
|
||||||
|
public interface SampleHttpStatusUseCase {
|
||||||
|
|
||||||
|
@McpTool(name = "oth.smp.sample.http.status",
|
||||||
|
title = "Sample external HTTP API status",
|
||||||
|
description = "Calls the configured sample HTTP API and returns its status.")
|
||||||
|
@ToolHint(register = false, categoryKey = "smp", mappingId = "HTTP_SAMPLE_001")
|
||||||
|
SampleHttpStatusResponse execute();
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.shinhanlife.dap.mcc.biz.smp.usecase.impl;
|
||||||
|
|
||||||
|
import io.shinhanlife.dap.mcc.biz.smp.dto.SampleHttpStatusResponse;
|
||||||
|
import io.shinhanlife.dap.mcc.biz.smp.usecase.SampleHttpStatusUseCase;
|
||||||
|
import io.shinhanlife.dap.mcc.infra.itrf.http.sample.SampleHttpApiClient;
|
||||||
|
import io.shinhanlife.dap.mcc.infra.itrf.http.sample.SampleHttpApiResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SampleHttpStatusUseCaseImpl implements SampleHttpStatusUseCase {
|
||||||
|
|
||||||
|
private final SampleHttpApiClient sampleHttpApiClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleHttpStatusResponse execute() {
|
||||||
|
SampleHttpApiResponse response = sampleHttpApiClient.getStatus();
|
||||||
|
return new SampleHttpStatusResponse(response.status(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package io.shinhanlife.dap.mcc.infra.itrf.http.sample;
|
||||||
|
|
||||||
|
import io.shinhanlife.dap.lib.integration.http.component.AxhubHttpComponent;
|
||||||
|
import io.shinhanlife.dap.lib.integration.http.component.AxhubHttpDomain;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/** Example of a Tool-specific HTTP client using the configured AX HUB HTTP domain. */
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SampleHttpApiClient {
|
||||||
|
|
||||||
|
private final AxhubHttpComponent http;
|
||||||
|
|
||||||
|
public SampleHttpApiResponse getStatus() {
|
||||||
|
return http.call(AxhubHttpDomain.SAMPLE, "/status", null, SampleHttpApiResponse.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.shinhanlife.dap.mcc.infra.itrf.http.sample;
|
||||||
|
|
||||||
|
/** DTO matching the external API JSON response: { "status": "OK", "message": "..." }. */
|
||||||
|
public record SampleHttpApiResponse(String status, String message) {
|
||||||
|
}
|
||||||
@@ -43,6 +43,14 @@ axhub:
|
|||||||
url: http://localhost:8081
|
url: http://localhost:8081
|
||||||
tool:
|
tool:
|
||||||
url: ${AXHUB_TOOL_URL:http://localhost:${server.port}}
|
url: ${AXHUB_TOOL_URL:http://localhost:${server.port}}
|
||||||
|
# Registered outbound HTTP APIs. Tool code selects the domain name, never a free-form URL.
|
||||||
|
http:
|
||||||
|
api-list:
|
||||||
|
- name: sample
|
||||||
|
domain: ${AXHUB_SAMPLE_HTTP_DOMAIN:http://localhost:8099}
|
||||||
|
path: ""
|
||||||
|
method: GET
|
||||||
|
biz-pod: false
|
||||||
|
|
||||||
sol:
|
sol:
|
||||||
req-detail:
|
req-detail:
|
||||||
|
|||||||
Reference in New Issue
Block a user