diff --git a/clients/line-bot-client-base/src/main/java/com/linecorp/bot/client/base/exception/AbstractLineClientException.java b/clients/line-bot-client-base/src/main/java/com/linecorp/bot/client/base/exception/AbstractLineClientException.java index 326b0c2cd..6f861f608 100644 --- a/clients/line-bot-client-base/src/main/java/com/linecorp/bot/client/base/exception/AbstractLineClientException.java +++ b/clients/line-bot-client-base/src/main/java/com/linecorp/bot/client/base/exception/AbstractLineClientException.java @@ -18,7 +18,10 @@ import java.io.IOException; import java.net.URL; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import okhttp3.Headers; import okhttp3.Response; @SuppressWarnings("serial") @@ -28,7 +31,7 @@ public class AbstractLineClientException extends IOException { public AbstractLineClientException(Response response, String message, IOException ioException) { super("API returns error: code=" + response.code() + " requestUrl=" + response.request().url() - + " requestId=" + response.headers().get("x-line-request-id") + + headerInfo(response.headers()) + " " + message, ioException); this.response = response; } @@ -36,7 +39,7 @@ public AbstractLineClientException(Response response, String message, IOExceptio public AbstractLineClientException(Response response, String message) { super("API returns error: code=" + response.code() + " requestUrl=" + response.request().url() - + " requestId=" + response.headers().get("x-line-request-id") + + headerInfo(response.headers()) + " " + message); this.response = response; } @@ -52,4 +55,21 @@ public URL getRequestUrl() { public String getRequestId() { return response.headers().get("x-line-request-id"); } + + public String getHeader(String name) { + return response.headers().get(name); + } + + private static String headerInfo(Headers headers) { + String headerInfo = StreamSupport.stream(headers.spliterator(), false) + .filter(it -> it.getFirst().startsWith("x-line-")) + .sorted((a, b) -> a.getFirst().compareTo(b.getSecond())) + .map(it -> it.getFirst() + "=" + it.getSecond()) + .collect(Collectors.joining(" ")); + if (headerInfo.isEmpty()) { + return ""; + } else { + return " " + headerInfo; + } + } } diff --git a/clients/line-bot-client-base/src/test/java/com/linecorp/bot/client/base/exception/AbstractLineClientExceptionTest.java b/clients/line-bot-client-base/src/test/java/com/linecorp/bot/client/base/exception/AbstractLineClientExceptionTest.java new file mode 100644 index 000000000..2c8b269ef --- /dev/null +++ b/clients/line-bot-client-base/src/test/java/com/linecorp/bot/client/base/exception/AbstractLineClientExceptionTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2023 LINE Corporation + * + * LINE Corporation licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package com.linecorp.bot.client.base.exception; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.net.URL; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import okhttp3.Headers; +import okhttp3.Request; +import okhttp3.Response; + + +public class AbstractLineClientExceptionTest { + + private Response response; + + @BeforeEach + void setUp() { + response = mock(Response.class); + Request request = new Request.Builder().url("https://example.com").build(); + + when(response.request()).thenReturn(request); + when(response.code()).thenReturn(200); + Headers headers = Headers.of(Map.of( + "x-line-example", "headerValue", + "x-line-request-id", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + )); + when(response.headers()).thenReturn(headers); + } + + @Test + void constructorWithIoException() { + IOException ioException = new IOException("test exception"); + AbstractLineClientException exception = new AbstractLineClientException(response, "test message", ioException); + + assertThat(exception).isNotNull(); + assertThat(exception.getMessage()).isEqualTo("API returns error: code=200 requestUrl=https://example.com/ x-line-example=headerValue x-line-request-id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx test message"); assertThat(exception.getCode()).isEqualTo(200); + assertThat(exception.getCause()).isEqualTo(ioException); + } + + @Test + void constructorNoException() { + AbstractLineClientException exception = new AbstractLineClientException(response, "test message"); + + assertThat(exception).isNotNull(); + assertThat(exception.getMessage()).isEqualTo("API returns error: code=200 requestUrl=https://example.com/ x-line-example=headerValue x-line-request-id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx test message"); assertThat(exception.getCode()).isEqualTo(200); + assertThat(exception.getCause()).isNull(); + } + + @Test + void getRequestUrl() throws Exception { + AbstractLineClientException exception = new AbstractLineClientException(response, "test message"); + assertThat(exception.getRequestUrl()).isEqualTo(new URL("https://example.com/")); + } + + @Test + void getRequestId() { + AbstractLineClientException exception = new AbstractLineClientException(response, "test message"); + assertThat(exception.getRequestId()).isEqualTo("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + } + + @Test + void getHeader() { + AbstractLineClientException exception = new AbstractLineClientException(response, "test message"); + assertThat(exception.getHeader("x-line-example")).isEqualTo("headerValue"); + } +}