From d061fb079dc978b9192a36921cf1f2201edcba52 Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Thu, 11 Jun 2026 20:42:59 +0800 Subject: [PATCH] fix: fix root request path encoding --- CHANGELOG.md | 1 + .../sdk/requests/RootRequestBuilder.java | 2 +- .../sdk/requests/RootRequestBuilderTest.java | 45 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/stellar/sdk/requests/RootRequestBuilderTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 33f518aae..8496490d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Pending ### Update +- fix: make `RootRequestBuilder` request the Horizon root endpoint as `/` instead of the percent-encoded `/%2F` path. - fix: make Horizon request builder URL generation idempotent so repeated `buildUri()` or `execute()` calls on the same builder do not duplicate path segments. - docs: add an [Agent Skill](https://agentskills.io/) for the Java Stellar SDK under `skills/`, plus Claude Code plugin manifests in `.claude-plugin/`. The skill gives AI coding agents concise, Stellar-specific guidance (transactions, operations, Horizon, Soroban, XDR/SCVal, and SEP protocols) when generating application code with `stellar-sdk`. - feat: add SEP-0046, SEP-0047, and SEP-0048 contract introspection support. New `ContractMeta`, `ContractSpec`, and `ContractInfo` wrappers under `org.stellar.sdk.contract` parse contract Wasm metadata and interface specs locally. `SorobanServer` adds `getContractWasm`, `getContractWasmByHash`, `getContractMeta`, `getContractSpec`, and `getContractInfo` for RPC-backed retrieval. diff --git a/src/main/java/org/stellar/sdk/requests/RootRequestBuilder.java b/src/main/java/org/stellar/sdk/requests/RootRequestBuilder.java index ac7946d55..0c0a1fb23 100644 --- a/src/main/java/org/stellar/sdk/requests/RootRequestBuilder.java +++ b/src/main/java/org/stellar/sdk/requests/RootRequestBuilder.java @@ -9,7 +9,7 @@ /** Builds requests connected to root. */ public class RootRequestBuilder extends RequestBuilder { public RootRequestBuilder(OkHttpClient httpClient, HttpUrl serverURI) { - super(httpClient, serverURI, "/"); + super(httpClient, serverURI, null); } /** diff --git a/src/test/java/org/stellar/sdk/requests/RootRequestBuilderTest.java b/src/test/java/org/stellar/sdk/requests/RootRequestBuilderTest.java new file mode 100644 index 000000000..798039d01 --- /dev/null +++ b/src/test/java/org/stellar/sdk/requests/RootRequestBuilderTest.java @@ -0,0 +1,45 @@ +package org.stellar.sdk.requests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.Test; +import org.stellar.sdk.Server; +import org.stellar.sdk.exception.BadRequestException; + +public class RootRequestBuilderTest { + @Test + public void testRoot() { + Server server = new Server("https://horizon-testnet.stellar.org"); + + assertEquals("https://horizon-testnet.stellar.org/", server.root().buildUri().toString()); + + server.close(); + } + + @Test + public void testRootRequestPath() throws IOException, InterruptedException { + MockWebServer mockWebServer = new MockWebServer(); + mockWebServer.enqueue(new MockResponse().setResponseCode(404)); + mockWebServer.start(); + Server server = new Server(mockWebServer.url("").toString()); + + try { + server.root().execute(); + fail("expected root request to return 404"); + } catch (BadRequestException e) { + assertEquals(404, e.getCode().intValue()); + + RecordedRequest request = mockWebServer.takeRequest(); + assertEquals("GET", request.getMethod()); + assertEquals("/", request.getPath()); + } finally { + server.close(); + mockWebServer.shutdown(); + } + } +}