From da840a24bc2cff02cfe24b2445408633bf4842af Mon Sep 17 00:00:00 2001 From: Fredrik Busklein Date: Wed, 22 Jul 2026 12:36:44 +0200 Subject: [PATCH] Use raw path when building request signature The signature is computed over the URL path, but getPath() read the decoded path from URI#getPath() rather than the encoded form actually transmitted. Any path with percent-encoded characters therefore produced a signature the server could not reproduce, and the request was refused. Read the path via URI#getRawPath() so client and server canonicalize the same bytes. Tests cover an encoded path and a plain-ASCII path. --- .../interceptor/ApacheHttpRequestToSign.java | 2 +- .../interceptor/ApacheHttpRequestToSignTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSign.java b/src/main/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSign.java index bada59b4..2dee0b97 100644 --- a/src/main/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSign.java +++ b/src/main/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSign.java @@ -49,7 +49,7 @@ public SortedMap getHeaders() { @Override public String getPath() { try { - String path = clientRequest.getUri().getPath(); + String path = clientRequest.getUri().getRawPath(); return path != null ? path : ""; } catch (URISyntaxException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/src/test/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSignTest.java b/src/test/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSignTest.java index 869163ac..a18e43e8 100644 --- a/src/test/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSignTest.java +++ b/src/test/java/no/digipost/api/client/internal/http/request/interceptor/ApacheHttpRequestToSignTest.java @@ -16,6 +16,7 @@ package no.digipost.api.client.internal.http.request.interceptor; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -23,6 +24,18 @@ public class ApacheHttpRequestToSignTest { + @Test + public void getPathReturnsEncodedPath() { + BasicClassicHttpRequest request = new BasicClassicHttpRequest("GET", "https://api.digipost.no/api/documents/%C3%86%20%C3%98/send"); + assertThat(new ApacheHttpRequestToSign(request).getPath(), is("/api/documents/%C3%86%20%C3%98/send")); + } + + @Test + public void getPathLeavesPlainAsciiPathUnchanged() { + BasicClassicHttpRequest request = new BasicClassicHttpRequest("GET", "https://api.digipost.no/api/documents/send"); + assertThat(new ApacheHttpRequestToSign(request).getPath(), is("/api/documents/send")); + } + @Test public void testStandardQuery(){ String s = ApacheHttpRequestToSign.queryParametersFromURI("http://www.idontknowwhatifeel.com?query=1&query=2");