From 9735750cc33e19d0fa70c05c9ba0e98f3d4d1c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20M=2E=20Ottestad?= Date: Mon, 29 Sep 2025 13:30:43 +0200 Subject: [PATCH] Strengthen base URI transaction regression test --- .../http/client/RDF4JProtocolSession.java | 8 +- .../http/client/RDF4JProtocolSessionTest.java | 47 ++++++++++ .../server/RemoteRepositoryBaseUriIT.java | 90 +++++++++++++++++++ 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 tools/server/src/test/java/org/eclipse/rdf4j/http/server/RemoteRepositoryBaseUriIT.java diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSession.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSession.java index 9b32d23f023..1aa195b2b06 100644 --- a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSession.java +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSession.java @@ -1069,9 +1069,11 @@ protected void upload(HttpEntity reqEntity, String baseURI, boolean overwrite, b for (String encodedContext : Protocol.encodeContexts(contexts)) { url.addParameter(Protocol.CONTEXT_PARAM_NAME, encodedContext); } - if (baseURI != null && !baseURI.trim().isEmpty()) { - String encodedBaseURI = Protocol.encodeValue(SimpleValueFactory.getInstance().createIRI(baseURI)); - url.setParameter(Protocol.BASEURI_PARAM_NAME, encodedBaseURI); + if (baseURI != null) { + String trimmedBaseURI = baseURI.trim(); + if (!trimmedBaseURI.isEmpty()) { + url.setParameter(Protocol.BASEURI_PARAM_NAME, trimmedBaseURI); + } } if (preserveNodeIds) { url.setParameter(Protocol.PRESERVE_BNODE_ID_PARAM_NAME, "true"); diff --git a/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSessionTest.java b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSessionTest.java index 98354a646bb..d5c3bc6783f 100644 --- a/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSessionTest.java +++ b/core/http/client/src/test/java/org/eclipse/rdf4j/http/client/RDF4JProtocolSessionTest.java @@ -15,6 +15,7 @@ import static org.mockserver.model.HttpResponse.response; import java.io.ByteArrayInputStream; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -184,6 +185,52 @@ public void testRemoveDataTransactionFollowsRedirectOnDelete(MockServerClient cl ); } + @Test + public void testAddDataTransactionUsesPlainBaseURI(MockServerClient client) throws Exception { + RDF4JProtocolSession session = getRDF4JSession(); + + String transactionsLocation = Protocol.getTransactionsLocation(session.getRepositoryURL()); + URI transactionsURI = URI.create(transactionsLocation); + String transactionLocation = transactionsLocation + "/1"; + URI transactionURI = URI.create(transactionLocation); + + client.when( + request() + .withMethod("POST") + .withPath(transactionsURI.getPath()), + Times.once()) + .respond(response().withStatusCode(201).withHeader("Location", transactionLocation)); + + client.when( + request() + .withMethod("PUT") + .withPath(transactionURI.getPath()) + .withQueryStringParameter("action", "ADD"), + Times.once()) + .respond(response().withStatusCode(204)); + + session.beginTransaction(IsolationLevels.SERIALIZABLE); + + String baseIRI = "http://example.com/"; + ByteArrayInputStream data = new ByteArrayInputStream(" ." + .getBytes(StandardCharsets.UTF_8)); + session.addData(data, baseIRI, RDFFormat.TURTLE); + + client.verify( + request() + .withMethod("PUT") + .withPath(transactionURI.getPath()) + .withQueryStringParameter("baseURI", baseIRI), + VerificationTimes.once()); + + HttpRequest[] recordedRequests = client.retrieveRecordedRequests( + request().withMethod("PUT") + .withPath(transactionURI.getPath()) + .withQueryStringParameter("action", "ADD")); + assertThat(recordedRequests).hasSize(1); + assertThat(recordedRequests[0].getFirstQueryStringParameter("baseURI")).isEqualTo(baseIRI); + } + @Test public void testUpdateRepositoryExecutesPost(MockServerClient client) throws Exception { RepositoryConfig config = new RepositoryConfig("test"); diff --git a/tools/server/src/test/java/org/eclipse/rdf4j/http/server/RemoteRepositoryBaseUriIT.java b/tools/server/src/test/java/org/eclipse/rdf4j/http/server/RemoteRepositoryBaseUriIT.java new file mode 100644 index 00000000000..334aca95bb5 --- /dev/null +++ b/tools/server/src/test/java/org/eclipse/rdf4j/http/server/RemoteRepositoryBaseUriIT.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2024 Eclipse RDF4J contributors. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + ******************************************************************************/ +package org.eclipse.rdf4j.http.server; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayInputStream; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.rdf4j.http.protocol.Protocol; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.util.Values; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.http.HTTPRepository; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class RemoteRepositoryBaseUriIT { + + private static TestServer server; + + @BeforeAll + public static void startServer() throws Exception { + server = new TestServer(); + try { + server.start(); + } catch (Exception e) { + server.stop(); + throw e; + } + } + + @AfterAll + public static void stopServer() throws Exception { + server.stop(); + } + + @Test + public void testAddDataUsesPlainBaseURI() throws Exception { + Repository repository = new HTTPRepository( + Protocol.getRepositoryLocation(TestServer.SERVER_URL, TestServer.TEST_REPO_ID)); + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.clear(); + connection.commit(); + } + + String baseIRI = "http://example.com/base/"; + String rdfXml = String.join("\n", + "", + "", + " ", + " ", + " ", + ""); + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(new ByteArrayInputStream(rdfXml.getBytes(java.nio.charset.StandardCharsets.UTF_8)), baseIRI, + RDFFormat.RDFXML); + connection.commit(); + } + + try (RepositoryConnection connection = repository.getConnection()) { + List statements = connection.getStatements(null, null, null, false) + .stream() + .collect(Collectors.toList()); + + assertThat(statements).hasSize(1); + Statement statement = statements.get(0); + assertThat(statement.getSubject()).isEqualTo(Values.iri(baseIRI + "relative")); + assertThat(statement.getPredicate()).isEqualTo(RDF.TYPE); + assertThat(statement.getObject()).isEqualTo(Values.iri("http://example.com/Type")); + } + } +}