This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 33d2fa0ff0 GH-3448: Choose HTTP headers for non-parsed sparql queries 
based on API usage.
33d2fa0ff0 is described below

commit 33d2fa0ff02cf16c81926e11b1283c59f5b520aa
Author: Claus Stadler <[email protected]>
AuthorDate: Mon Sep 15 22:12:34 2025 +0200

    GH-3448: Choose HTTP headers for non-parsed sparql queries based on API 
usage.
---
 .../org/apache/jena/http/sys/ExecHTTPBuilder.java  |  53 ++++++-
 .../jena/sparql/exec/http/QueryExecHTTP.java       | 102 ++++++++++----
 .../sparql/exec/http/QueryExecHTTPBuilder.java     |   6 +-
 .../exec/http/QueryExecutionHTTPBuilder.java       |   6 +-
 .../examples/RDFConnectionExampleDBpedia01.java    |  55 ++++++++
 .../java/org/apache/jena/rdflink/RDFLinkHTTP.java  | 156 +++------------------
 .../apache/jena/rdflink/RDFLinkHTTPBuilder.java    |   1 +
 .../jena/rdfconnection/TS_RDFConnection.java       |   1 +
 .../jena/rdfconnection/TestRDFConnectionHTTP.java  |  99 -------------
 .../TestRDFConnectionHTTPHeaders.java              | 153 ++++++++++++++++++++
 .../java/org/apache/jena/rdflink/TS_RDFLink.java   |   1 +
 .../jena/rdflink/TestRDFLinkHTTPHeaders.java       |  97 +++++++++++++
 12 files changed, 467 insertions(+), 263 deletions(-)

diff --git 
a/jena-arq/src/main/java/org/apache/jena/http/sys/ExecHTTPBuilder.java 
b/jena-arq/src/main/java/org/apache/jena/http/sys/ExecHTTPBuilder.java
index a7b3f6c471..c62c468534 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/sys/ExecHTTPBuilder.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/sys/ExecHTTPBuilder.java
@@ -25,6 +25,8 @@ import java.util.concurrent.TimeUnit;
 import org.apache.jena.graph.Node;
 import org.apache.jena.http.HttpEnv;
 import org.apache.jena.query.*;
+import org.apache.jena.riot.WebContent;
+import org.apache.jena.riot.web.HttpNames;
 import org.apache.jena.sparql.core.Var;
 import org.apache.jena.sparql.engine.binding.Binding;
 import org.apache.jena.sparql.exec.http.Params;
@@ -50,8 +52,15 @@ public abstract class ExecHTTPBuilder<X, Y> {
     protected Params params = Params.create();
     private ContextAccumulator contextAcc = 
ContextAccumulator.newBuilder(()->ARQ.getContext());
 
-    // Accept choice by the application
-    protected String appAcceptHeader = null;
+    // Accept choice by the application. Deprecated - Superseded by 
acceptHeader(String) which sets all header fields explicitly.
+    @Deprecated(forRemoval = true)
+    protected String appAcceptHeader     = null;
+
+    protected String selectAcceptHeader  = 
WebContent.defaultSparqlResultsHeader;
+    protected String askAcceptHeader     = WebContent.defaultSparqlAskHeader;
+    protected String graphAcceptHeader   = WebContent.defaultGraphAcceptHeader;
+    protected String datasetAcceptHeader = 
WebContent.defaultDatasetAcceptHeader;
+
     protected long timeout = -1;
     protected TimeUnit timeoutUnit = null;
 
@@ -253,22 +262,58 @@ public abstract class ExecHTTPBuilder<X, Y> {
         return thisBuilder();
     }
 
+    /** Setting this header overrides any other header. */
     public Y acceptHeader(String acceptHeader) {
         Objects.requireNonNull(acceptHeader);
         this.appAcceptHeader = acceptHeader;
+        this.selectAcceptHeader = acceptHeader;
+        this.askAcceptHeader = acceptHeader;
+        this.graphAcceptHeader = acceptHeader;
+        this.datasetAcceptHeader = acceptHeader;
+        return thisBuilder();
+    }
+
+    /** Set the HTTP {@code Accept:} header used to when making a SPARQL 
Protocol SELECT query. */
+    public Y acceptHeaderSelectQuery(String acceptSelectHeader) {
+        this.selectAcceptHeader = acceptSelectHeader;
+        return thisBuilder();
+    }
+
+    /** Set the HTTP {@code Accept:} header used to when making a SPARQL 
Protocol ASK query. */
+    public Y acceptHeaderAskQuery(String acceptAskHeader) {
+        this.askAcceptHeader = acceptAskHeader;
+        return thisBuilder();
+    }
+
+    /** Set the HTTP {@code Accept:} header used to fetch RDF graph using the 
SPARQL CONSTRUCT and DESCRIBE query types. */
+    public Y acceptHeaderGraph(String acceptGraph) {
+        this.graphAcceptHeader = acceptGraph;
+        return thisBuilder();
+    }
+
+    /** Set the HTTP {@code Accept:} header used to when making a SPARQL 
Protocol CONSTRUCT dataset query.
+     * This is a Jena extension. */
+    public Y acceptHeaderDataset(String acceptDataset) {
+        this.datasetAcceptHeader = acceptDataset;
         return thisBuilder();
     }
 
     public Y httpHeader(String headerName, String headerValue) {
         Objects.requireNonNull(headerName);
         Objects.requireNonNull(headerValue);
-        this.httpHeaders.put(headerName, headerValue);
+
+        // Special handling of an Accept-Header.
+        if (headerName.equals(HttpNames.hAccept)) {
+            acceptHeader(headerValue);
+        } else {
+            this.httpHeaders.put(headerName, headerValue);
+        }
         return thisBuilder();
     }
 
     public Y httpHeaders(Map<String, String> headers) {
         Objects.requireNonNull(headers);
-        this.httpHeaders.putAll(headers);
+        headers.forEach(this::httpHeader);
         return thisBuilder();
     }
 
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTP.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTP.java
index 9a1d52202d..953819a18b 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTP.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTP.java
@@ -100,15 +100,14 @@ public class QueryExecHTTP implements QueryExec {
     private long readTimeout = -1;
     private TimeUnit readTimeoutUnit = TimeUnit.MILLISECONDS;
 
-    // Content Types: these list the standard formats and also include */*.
-    private final String selectAcceptheader    = 
WebContent.defaultSparqlResultsHeader;
-    private final String askAcceptHeader       = 
WebContent.defaultSparqlAskHeader;
-    private final String describeAcceptHeader  = 
WebContent.defaultGraphAcceptHeader;
-    private final String constructAcceptHeader = 
WebContent.defaultGraphAcceptHeader;
-    private final String datasetAcceptHeader   = 
WebContent.defaultDatasetAcceptHeader;
+    private final String selectAcceptHeader;
+    private final String askAcceptHeader;
+    private final String graphAcceptHeader;
+    private final String datasetAcceptHeader;
 
     // If this is non-null, it overrides the use of any Content-Type above.
-    private String appProvidedAcceptHeader         = null;
+    @Deprecated(forRemoval = true) // Deprecated in favor of setting the other 
header fields.
+    private String overrideAcceptHeader         = null;
 
     // Received content type
     private String httpResponseContentType = null;
@@ -119,10 +118,45 @@ public class QueryExecHTTP implements QueryExec {
     private HttpClient httpClient = HttpEnv.getDftHttpClient();
     private Map<String, String> httpHeaders;
 
+    /**
+     * This constructor is superseded by the other one which has more 
parameters.
+     * The recommended way to create instances of this class is via {@link 
QueryExecHTTPBuilder}.
+     */
+    @Deprecated(forRemoval = true)
     public QueryExecHTTP(String serviceURL, Query query, String queryString, 
int urlLimit,
+            HttpClient httpClient, Map<String, String> httpHeaders, Params 
params, Context context,
+            List<String> defaultGraphURIs, List<String> namedGraphURIs,
+            QuerySendMode sendMode, String overrideAcceptHeader,
+            long timeout, TimeUnit timeoutUnit) {
+        // Content Types: these list the standard formats and also include */*
+        this(serviceURL, query, queryString, urlLimit,
+                httpClient, httpHeaders, params, context,
+                defaultGraphURIs, namedGraphURIs,
+                sendMode,
+                dft(overrideAcceptHeader, 
WebContent.defaultSparqlResultsHeader),
+                dft(overrideAcceptHeader, WebContent.defaultSparqlAskHeader),
+                dft(overrideAcceptHeader, WebContent.defaultGraphAcceptHeader),
+                dft(overrideAcceptHeader, 
WebContent.defaultDatasetAcceptHeader),
+                timeout, timeoutUnit);
+
+        // Handling of legacy overrideAcceptHeader.
+        this.overrideAcceptHeader = overrideAcceptHeader;
+        // Important - handled as special case because the defaults vary by 
query type.
+        if ( httpHeaders.containsKey(HttpNames.hAccept) ) {
+            if ( this.overrideAcceptHeader != null ) {
+                String acceptHeader = httpHeaders.get(HttpNames.hAccept);
+                this.overrideAcceptHeader = acceptHeader;
+            }
+            this.httpHeaders.remove(HttpNames.hAccept);
+        }
+    }
+
+    protected QueryExecHTTP(String serviceURL, Query query, String 
queryString, int urlLimit,
                          HttpClient httpClient, Map<String, String> 
httpHeaders, Params params, Context context,
                          List<String> defaultGraphURIs, List<String> 
namedGraphURIs,
-                         QuerySendMode sendMode, String explicitAcceptHeader,
+                         QuerySendMode sendMode,
+                         String selectAcceptHeader, String askAcceptHeader,
+                         String graphAcceptHeader, String datasetAcceptHeader,
                          long timeout, TimeUnit timeoutUnit) {
         this.context = ( context == null ) ? ARQ.getContext().copy() : 
context.copy();
         this.service = serviceURL;
@@ -133,13 +167,10 @@ public class QueryExecHTTP implements QueryExec {
         this.defaultGraphURIs = defaultGraphURIs;
         this.namedGraphURIs = namedGraphURIs;
         this.sendMode = Objects.requireNonNull(sendMode);
-        this.appProvidedAcceptHeader = explicitAcceptHeader;
-        // Important - handled as special case because the defaults vary by 
query type.
-        if ( httpHeaders.containsKey(HttpNames.hAccept) ) {
-            if ( this.appProvidedAcceptHeader != null )
-                this.appProvidedAcceptHeader = 
httpHeaders.get(HttpNames.hAccept);
-            this.httpHeaders.remove(HttpNames.hAccept);
-        }
+        this.selectAcceptHeader = selectAcceptHeader;
+        this.askAcceptHeader = askAcceptHeader;
+        this.graphAcceptHeader = graphAcceptHeader;
+        this.datasetAcceptHeader = datasetAcceptHeader;
         this.httpHeaders = httpHeaders;
         this.params = params;
         this.readTimeout = timeout;
@@ -147,9 +178,30 @@ public class QueryExecHTTP implements QueryExec {
         this.httpClient = HttpLib.dft(httpClient, HttpEnv.getDftHttpClient());
     }
 
-    /** Getter for the appProvidedAcceptHeader. Only used for testing. */
+    public String getAcceptHeaderSelect() {
+        return selectAcceptHeader;
+    }
+
+    public String getAcceptHeaderAsk() {
+        return askAcceptHeader;
+    }
+
+    public String getAcceptHeaderDescribe() {
+        return graphAcceptHeader;
+    }
+
+    public String getAcceptHeaderConstructGraph() {
+        return graphAcceptHeader;
+    }
+
+    public String getAcceptHeaderConstructDataset() {
+        return datasetAcceptHeader;
+    }
+
+    /** Getter for the override accept header. Only used for testing. */
+    @Deprecated(forRemoval = true)
     public String getAppProvidedAcceptHeader() {
-        return appProvidedAcceptHeader;
+        return overrideAcceptHeader;
     }
 
     /** The Content-Type response header received (null before the remote 
operation is attempted). */
@@ -167,7 +219,7 @@ public class QueryExecHTTP implements QueryExec {
 
     private RowSet execRowSet() {
         // Use the explicitly given header or the default selectAcceptheader
-        String thisAcceptHeader = dft(appProvidedAcceptHeader, 
selectAcceptheader);
+        String thisAcceptHeader = dft(overrideAcceptHeader, 
selectAcceptHeader);
 
         HttpRequest request = effectiveHttpRequest(thisAcceptHeader);
         HttpResponse<InputStream> response = executeQuery(request);
@@ -214,7 +266,7 @@ public class QueryExecHTTP implements QueryExec {
     public boolean ask() {
         checkNotClosed();
         check(QueryType.ASK);
-        String thisAcceptHeader = dft(appProvidedAcceptHeader, 
askAcceptHeader);
+        String thisAcceptHeader = dft(overrideAcceptHeader, askAcceptHeader);
         HttpRequest request = effectiveHttpRequest(thisAcceptHeader);
         HttpResponse<InputStream> response = executeQuery(request);
         InputStream in = HttpLib.getInputStream(response);
@@ -262,14 +314,14 @@ public class QueryExecHTTP implements QueryExec {
     public Graph construct(Graph graph) {
         checkNotClosed();
         check(QueryType.CONSTRUCT);
-        return execGraph(graph, constructAcceptHeader);
+        return execGraph(graph, graphAcceptHeader);
     }
 
     @Override
     public Iterator<Triple> constructTriples() {
         checkNotClosed();
         check(QueryType.CONSTRUCT);
-        return execTriples(constructAcceptHeader);
+        return execTriples(graphAcceptHeader);
     }
 
     @Override
@@ -295,13 +347,13 @@ public class QueryExecHTTP implements QueryExec {
     public Graph describe(Graph graph) {
         checkNotClosed();
         check(QueryType.DESCRIBE);
-        return execGraph(graph, describeAcceptHeader);
+        return execGraph(graph, graphAcceptHeader);
     }
 
     @Override
     public Iterator<Triple> describeTriples() {
         checkNotClosed();
-        return execTriples(describeAcceptHeader);
+        return execTriples(graphAcceptHeader);
     }
 
     private Graph execGraph(Graph graph, String acceptHeader) {
@@ -354,7 +406,7 @@ public class QueryExecHTTP implements QueryExec {
     // ifNoContentType - some wild guess at the content type.
     private Pair<InputStream, Lang> execRdfWorker(String contentType, String 
ifNoContentType) {
         checkNotClosed();
-        String thisAcceptHeader = dft(appProvidedAcceptHeader, contentType);
+        String thisAcceptHeader = dft(overrideAcceptHeader, contentType);
         HttpRequest request = effectiveHttpRequest(thisAcceptHeader);
         HttpResponse<InputStream> response = executeQuery(request);
         InputStream in = HttpLib.getInputStream(response);
@@ -382,7 +434,7 @@ public class QueryExecHTTP implements QueryExec {
     public JsonArray execJson() {
         checkNotClosed();
         check(QueryType.CONSTRUCT_JSON);
-        String thisAcceptHeader = dft(appProvidedAcceptHeader, 
WebContent.contentTypeJSON);
+        String thisAcceptHeader = dft(overrideAcceptHeader, 
WebContent.contentTypeJSON);
         HttpRequest request = effectiveHttpRequest(thisAcceptHeader);
         HttpResponse<InputStream> response = executeQuery(request);
         InputStream in = HttpLib.getInputStream(response);
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTPBuilder.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTPBuilder.java
index d861b7f5b5..86f0bba7e8 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTPBuilder.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecHTTPBuilder.java
@@ -49,7 +49,11 @@ public class QueryExecHTTPBuilder extends 
ExecHTTPBuilder<QueryExecHTTP, QueryEx
                                  hClient, new HashMap<>(httpHeaders), 
Params.create(params), cxt,
                                  copyArray(defaultGraphURIs),
                                  copyArray(namedGraphURIs),
-                                 sendMode, appAcceptHeader,
+                                 sendMode,
+                                 selectAcceptHeader,
+                                 askAcceptHeader,
+                                 graphAcceptHeader,
+                                 datasetAcceptHeader,
                                  timeout, timeoutUnit);
     }
 
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecutionHTTPBuilder.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecutionHTTPBuilder.java
index e962491291..fa8cc473c0 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecutionHTTPBuilder.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/exec/http/QueryExecutionHTTPBuilder.java
@@ -53,7 +53,11 @@ public class QueryExecutionHTTPBuilder
         QueryExecHTTP qExec = new QueryExecHTTP(serviceURL, queryActual, 
queryStringActual, urlLimit,
                                                 hClient, new 
HashMap<>(httpHeaders), Params.create(params), cxt,
                                                 copyArray(defaultGraphURIs), 
copyArray(namedGraphURIs),
-                                                sendMode, appAcceptHeader,
+                                                sendMode,
+                                                selectAcceptHeader,
+                                                askAcceptHeader,
+                                                graphAcceptHeader,
+                                                datasetAcceptHeader,
                                                 timeout, timeoutUnit);
         return new QueryExecutionHTTP(qExec);
     }
diff --git 
a/jena-examples/src/main/java/rdfconnection/examples/RDFConnectionExampleDBpedia01.java
 
b/jena-examples/src/main/java/rdfconnection/examples/RDFConnectionExampleDBpedia01.java
new file mode 100644
index 0000000000..d587fec47c
--- /dev/null
+++ 
b/jena-examples/src/main/java/rdfconnection/examples/RDFConnectionExampleDBpedia01.java
@@ -0,0 +1,55 @@
+package rdfconnection.examples;
+
+import java.util.List;
+
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.query.ResultSetFormatter;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionRemote;
+import org.apache.jena.riot.WebContent;
+import org.apache.jena.sparql.resultset.ResultsFormat;
+
+/**
+ * Example that showcases querying DBpedia with disabled parse check and
+ * different accept headers.
+ * <p>
+ *
+ * The expected output should be similar to this snippet:
+ * <pre>
+ * Trying to query with content type: application/sparql-results+thrift
+ * Request failed: Not Acceptable
+ *
+ * Trying to query with content type: application/sparql-results+json
+ * -------------------------
+ * | l                     |
+ * =========================
+ * | "Jena (Framework)"@de |
+ * -------------------------
+ * </pre>
+ */
+public class RDFConnectionExampleDBpedia01 {
+    public static void main(String[] args) {
+        List<String> acceptHeaders = 
List.of(WebContent.contentTypeResultsThrift, WebContent.contentTypeResultsJSON);
+
+        // Note that the query string uses the prefix 'rdfs:' without 
declaring it.
+        // The DBpedia server can parse such a query against its configured 
default prefixes.
+        String queryString = "SELECT * { 
<http://dbpedia.org/resource/Apache_Jena> rdfs:label ?l } ORDER BY ?l LIMIT 1";
+
+        for (String acceptHeader : acceptHeaders) {
+            System.out.println("Trying to query with content type: " + 
acceptHeader);
+            try (RDFConnection conn = 
RDFConnectionRemote.service("http://dbpedia.org/sparql";)
+                    
.acceptHeaderSelectQuery(acceptHeader).parseCheckSPARQL(false).build()) {
+                try (QueryExecution qe = conn.query(queryString)) {
+                    ResultSet rs = qe.execSelect();
+                    ResultSetFormatter.output(System.out, rs, 
ResultsFormat.FMT_TEXT);
+                } catch (Exception e) {
+                    System.out.println("Request failed: " + e.getMessage());
+                }
+            }
+            System.out.println();
+        }
+
+        System.out.println("Done.");
+    }
+}
diff --git 
a/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTP.java 
b/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTP.java
index 2a7006dc8f..b4edd28ece 100644
--- a/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTP.java
+++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTP.java
@@ -26,10 +26,9 @@ import org.apache.jena.atlas.lib.InternalErrorException;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.http.HttpEnv;
+import org.apache.jena.http.HttpLib;
 import org.apache.jena.query.*;
-import org.apache.jena.rdfconnection.JenaConnectionException;
 import org.apache.jena.riot.RDFFormat;
-import org.apache.jena.riot.WebContent;
 import org.apache.jena.sparql.ARQException;
 import org.apache.jena.sparql.core.DatasetGraph;
 import org.apache.jena.sparql.core.Transactional;
@@ -43,7 +42,6 @@ import org.apache.jena.sparql.exec.http.QueryExecHTTPBuilder;
 import org.apache.jena.sparql.exec.http.QuerySendMode;
 import org.apache.jena.sparql.exec.http.UpdateExecHTTPBuilder;
 import org.apache.jena.sparql.exec.http.UpdateSendMode;
-import org.apache.jena.sparql.util.Context;
 import org.apache.jena.system.Txn;
 import org.apache.jena.update.UpdateFactory;
 import org.apache.jena.update.UpdateRequest;
@@ -74,7 +72,8 @@ public class RDFLinkHTTP implements RDFLink {
     protected final String acceptDataset;
     protected final String acceptSelectResult;
     protected final String acceptAskResult;
-    // All purpose SPARQL results header used if above specific cases do not 
apply.
+
+    // Fallback all purpose SPARQL results header used if above specific cases 
do not apply.
     protected final String acceptSparqlResults;
 
     // Whether to check SPARQL queries given as strings by parsing them.
@@ -107,7 +106,7 @@ public class RDFLinkHTTP implements RDFLink {
     protected RDFLinkHTTP(Transactional txnLifecycle, HttpClient httpClient, 
String destination,
                           String queryURL, String updateURL, String gspURL, 
RDFFormat outputQuads, RDFFormat outputTriples,
                           String acceptDataset, String acceptGraph,
-                          String acceptSparqlResults,
+                          String acceptSparqlResultsFallback,
                           String acceptSelectResult, String acceptAskResult,
                           boolean parseCheckQueries, boolean parseCheckUpdates,
                           QuerySendMode querySendMode, UpdateSendMode 
updateSendMode) {
@@ -126,7 +125,7 @@ public class RDFLinkHTTP implements RDFLink {
         this.outputTriples = outputTriples;
         this.acceptDataset = acceptDataset;
         this.acceptGraph = acceptGraph;
-        this.acceptSparqlResults = acceptSparqlResults;
+        this.acceptSparqlResults = acceptSparqlResultsFallback;
         this.acceptSelectResult = acceptSelectResult;
         this.acceptAskResult = acceptAskResult;
         this.parseCheckQueries = parseCheckQueries;
@@ -173,7 +172,7 @@ public class RDFLinkHTTP implements RDFLink {
     @Override
     public void queryRowSet(String queryString, Consumer<RowSet> rowSetAction) 
{
         Txn.executeRead(this, ()->{
-            try ( QueryExec qExec = query(queryString, QueryType.SELECT) ) {
+            try ( QueryExec qExec = query(queryString) ) {
                 RowSet rs = qExec.select();
                 rowSetAction.accept(rs);
             }
@@ -188,7 +187,7 @@ public class RDFLinkHTTP implements RDFLink {
     @Override
     public void querySelect(String queryString, Consumer<Binding> rowAction) {
         Txn.executeRead(this, ()->{
-            try ( QueryExec qExec = query(queryString, QueryType.SELECT) ) {
+            try ( QueryExec qExec = query(queryString) ) {
                 qExec.select().forEachRemaining(rowAction);
             }
         } );
@@ -199,7 +198,7 @@ public class RDFLinkHTTP implements RDFLink {
     public Graph queryConstruct(String queryString) {
         return
             Txn.calculateRead(this, ()->{
-                try ( QueryExec qExec = query(queryString, 
QueryType.CONSTRUCT) ) {
+                try ( QueryExec qExec = query(queryString) ) {
                     return qExec.construct();
                 }
             } );
@@ -210,7 +209,7 @@ public class RDFLinkHTTP implements RDFLink {
     public Graph queryDescribe(String queryString) {
         return
             Txn.calculateRead(this, ()->{
-                try ( QueryExec qExec = query(queryString, QueryType.DESCRIBE) 
) {
+                try ( QueryExec qExec = query(queryString) ) {
                     return qExec.describe();
                 }
             } );
@@ -221,33 +220,22 @@ public class RDFLinkHTTP implements RDFLink {
     public boolean queryAsk(String queryString) {
         return
             Txn.calculateRead(this, ()->{
-                try ( QueryExec qExec = query(queryString, QueryType.ASK) ) {
+                try ( QueryExec qExec = query(queryString) ) {
                     return qExec.ask();
                 }
             } );
     }
 
-    /**
-     * Operation that passed down the query type so the accept header can be 
set without parsing the query string.
-     * @param queryString
-     * @param queryType
-     * @return QueryExecution
-     */
-    protected QueryExec query(String queryString, QueryType queryType) {
-        Objects.requireNonNull(queryString);
-        return queryExec(null, queryString, queryType);
-    }
-
     @Override
     public QueryExec query(String queryString) {
         Objects.requireNonNull(queryString);
-        return queryExec(null, queryString, null);
+        return queryExec(null, queryString);
     }
 
     @Override
     public QueryExec query(Query query) {
         Objects.requireNonNull(query);
-        return queryExec(query, null, null);
+        return queryExec(query, null);
     }
 
     @Override
@@ -255,11 +243,11 @@ public class RDFLinkHTTP implements RDFLink {
         return createQExecBuilder();
     }
 
-    /** Create the QExec initialized with a query object or string. */
-    private QueryExec queryExec(Query query, String queryString, QueryType 
queryType) {
-        QueryExecHTTPBuilderOverRDFLinkHTTP builder = createQExecBuilder();
+    /** Create the QExec initialized with a query object or string. Only one 
argument is non-null. */
+    private QueryExec queryExec(Query query, String queryString) {
+        QueryExecHTTPBuilder builder = createQExecBuilder();
         if (queryString != null) {
-            builder.queryStringValidated(queryString, 
Syntax.defaultQuerySyntax, queryType);
+            builder.query(queryString);
         }
         if (query != null) {
             builder.query(query);
@@ -267,117 +255,19 @@ public class RDFLinkHTTP implements RDFLink {
         return QueryExecApp.create(builder, null, query, queryString);
     }
 
-    /**
-     * An internal subclass of {@link QueryExecHTTPBuilder} that overrides
-     * {@link #buildX(HttpClient, Query, String, Context)}
-     * in order to have the accept header field derived based on this {@link 
RDFLinkHTTP} configuration.
-     */
-    /* package */ class QueryExecHTTPBuilderOverRDFLinkHTTP
-        extends QueryExecHTTPBuilder
-    {
-        /** The query type. Never null. */
-        protected QueryType queryType = QueryType.UNKNOWN;
-
-        /** The parsed query is only needed for setting the appropriate HTTP 
header for construct quad queries. */
-        protected Query parsedQuery = null;
-
-        protected QueryExecHTTPBuilderOverRDFLinkHTTP() {
-            super();
-        }
-
-        /** This method wraps {@link #queryString(String)} and sets the 
additional attributes without further interpretation. */
-        protected QueryExecHTTPBuilder queryString(String queryString, 
QueryType queryType, Query parsedQuery) {
-            super.queryString(queryString);
-            this.queryType = queryType != null ? queryType : QueryType.UNKNOWN;
-            this.parsedQuery = parsedQuery;
-            return thisBuilder();
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public QueryExecHTTPBuilder queryString(String queryString) {
-             return queryString(queryString, null, null);
-        }
-
-        /** This method is far only called from RDFLinkHTTP. It validates the 
query string if parseCheckQueries is enabled.  */
-        protected QueryExecHTTPBuilder queryStringValidated(String 
queryString, Syntax syntax, QueryType fallbackQueryType) {
-            Query parsedQuery = parseCheck
-                    ? QueryFactory.create(queryString, syntax)
-                    : null;
-
-            QueryType finalQueryType = parsedQuery != null ? 
parsedQuery.queryType() : fallbackQueryType;
-            return queryString(queryString, finalQueryType, parsedQuery);
-        }
-
-        @Override
-        protected void setQuery(Query query, String queryStr) {
-            super.setQuery(query, queryStr);
-            parsedQuery = query;
-            queryType = query == null ? QueryType.UNKNOWN : query.queryType();
-        }
-
-        @Override
-        protected QueryExecHTTP buildX(HttpClient hClient, Query queryActual, 
String queryStringActual, Context cxt) {
-            // If the appAcceptHeader has not been explicitly set then derive 
it.
-            if (appAcceptHeader == null) {
-                String requestAcceptHeader = null;
-                // Use the most specific method.
-                switch(queryType) {
-                    case SELECT :
-                        if ( acceptSelectResult != null )
-                            requestAcceptHeader = 
RDFLinkHTTP.this.acceptSelectResult;
-                        break;
-                    case ASK :
-                        if ( acceptAskResult != null )
-                            requestAcceptHeader = 
RDFLinkHTTP.this.acceptAskResult;
-                        break;
-                    case DESCRIBE :
-                    case CONSTRUCT :
-                        // Best effort to handle construct quads. Requires a 
parsed query.
-                        if (parsedQuery != null && 
parsedQuery.isConstructQuad()) {
-                            if ( acceptDataset != null )
-                                requestAcceptHeader = 
RDFLinkHTTP.this.acceptDataset;
-                        } else {
-                            if ( acceptGraph != null )
-                                requestAcceptHeader = 
RDFLinkHTTP.this.acceptGraph;
-                        }
-                        break;
-                    case CONSTRUCT_JSON :
-                        requestAcceptHeader = WebContent.contentTypeJSON;
-                        break;
-                    case UNKNOWN :
-                        // All-purpose content type.
-                        if ( acceptSparqlResults != null ) {
-                            requestAcceptHeader = 
RDFLinkHTTP.this.acceptSparqlResults;
-                        } else {
-                            // No idea! Set an "anything" and hope.
-                            // (Reasonable chance this is going to end up as 
HTML though.)
-                            requestAcceptHeader = "*/*";
-                        }
-                        break;
-                    default :
-                        break;
-                }
-                // Make sure it was set somehow.
-                if ( requestAcceptHeader == null )
-                    throw new JenaConnectionException("No Accept header");
-
-                this.acceptHeader(requestAcceptHeader);
-            }
-
-            return super.buildX(hClient, queryActual, queryStringActual, cxt);
-        }
-    }
-
     /**
      * Create a builder, configured with the link setup.
      *
      * @param presetQueryType If non-null then the builder will force 
execution with this query type.
      */
-    private QueryExecHTTPBuilderOverRDFLinkHTTP createQExecBuilder() {
+    private QueryExecHTTPBuilder createQExecBuilder() {
         checkQuery();
-        QueryExecHTTPBuilderOverRDFLinkHTTP builder = new 
QueryExecHTTPBuilderOverRDFLinkHTTP();
-        
builder.endpoint(svcQuery).httpClient(httpClient).sendMode(querySendMode).parseCheck(parseCheckQueries);
+        QueryExecHTTPBuilder builder = QueryExecHTTP.newBuilder();
+        
builder.endpoint(svcQuery).httpClient(httpClient).sendMode(querySendMode).parseCheck(parseCheckQueries)
+            .acceptHeaderSelectQuery(HttpLib.dft(acceptSelectResult, 
acceptSparqlResults))
+            .acceptHeaderAskQuery(HttpLib.dft(acceptAskResult, 
acceptSparqlResults))
+            .acceptHeaderGraph(HttpLib.dft(acceptGraph, acceptSparqlResults))
+            .acceptHeaderDataset(HttpLib.dft(acceptDataset, 
acceptSparqlResults));
         return builder;
     }
 
diff --git 
a/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTPBuilder.java
 
b/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTPBuilder.java
index 8db4740a58..2b77cbf862 100644
--- 
a/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTPBuilder.java
+++ 
b/jena-rdfconnection/src/main/java/org/apache/jena/rdflink/RDFLinkHTTPBuilder.java
@@ -55,6 +55,7 @@ public class RDFLinkHTTPBuilder {
     protected RDFFormat     outputQuads        = HttpEnv.defaultQuadsFormat;
     protected RDFFormat     outputTriples      = HttpEnv.defaultTriplesFormat;
 
+    // The acceptGraph header is used for SPARQL CONSTRUCT, DESCRIBE and GSP 
GET.
     protected String        acceptGraph        = 
WebContent.defaultGraphAcceptHeader;
     protected String        acceptDataset      = 
WebContent.defaultDatasetAcceptHeader;
 
diff --git 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
index e13aefc42a..629de0d215 100644
--- 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
+++ 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TS_RDFConnection.java
@@ -29,6 +29,7 @@ import org.junit.platform.suite.api.Suite;
     , TestRDFConnectionLocalMRSW.class
     , TestLibRDFConn.class
     , TestRDFConnectionRewrapping.class
+    , TestRDFConnectionHTTPHeaders.class
 })
 
 public class TS_RDFConnection {}
diff --git 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTP.java
 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTP.java
deleted file mode 100644
index 8f5b7220a0..0000000000
--- 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTP.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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
- *
- *     http://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 org.apache.jena.rdfconnection;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-import org.apache.jena.query.Query;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QueryFactory;
-import org.apache.jena.riot.WebContent;
-import org.apache.jena.sparql.exec.QueryExec;
-import org.apache.jena.sparql.exec.http.QueryExecHTTP;
-
-public class TestRDFConnectionHTTP {
-
-    @Test
-    public void test_select_01() {
-        doAssert(WebContent.contentTypeXML, "SELECT * { ?s a ?o } LIMIT 10");
-    }
-
-    @Test
-    public void test_ask_01() {
-        doAssert(WebContent.contentTypeJSON, "ASK { ?s a ?o }");
-    }
-
-    @Test
-    public void test_constructTriples_01() {
-        doAssert(WebContent.contentTypeTurtle, "CONSTRUCT WHERE { ?s a ?o } 
LIMIT 10");
-    }
-
-    @Test
-    public void test_constructQuads_01() {
-        doAssert(WebContent.contentTypeTriG, "CONSTRUCT WHERE { GRAPH ?g{ ?s a 
?o } } LIMIT 10");
-    }
-
-    @Test
-    public void test_describe_01() {
-        doAssert(WebContent.contentTypeNTriples, "DESCRIBE <urn:x>");
-    }
-
-    private static RDFConnectionRemoteBuilder configureHeader(Query query, 
String header, RDFConnectionRemoteBuilder builder) {
-        return switch (query.queryType()) {
-        case SELECT -> builder.acceptHeaderSelectQuery(header);
-        case CONSTRUCT -> !query.isConstructQuad()
-                            ? builder.acceptHeaderGraph(header)
-                            : builder.acceptHeaderDataset(header);
-        case DESCRIBE -> builder.acceptHeaderGraph(header);
-        case ASK -> builder.acceptHeaderAskQuery(header);
-        default -> throw new UnsupportedOperationException("Unhandled query 
type for query: " + query);
-        };
-    }
-
-    /** Test whether the constructed QueryExec instance has the expected HTTP 
header set */
-    private static void doAssert(String expectedHeader, String queryString) {
-        Query query = QueryFactory.create(queryString);
-
-        try (RDFConnection conn = configureHeader(query, expectedHeader, 
RDFConnectionRemote.newBuilder())
-                .queryEndpoint("https://www.example.org/sparql";) // Should 
never be resolved
-                .build()) {
-            try (QueryExecution qe = conn.query(queryString)) {
-                QueryExecHTTP qeh = (QueryExecHTTP)QueryExec.adapt(qe);
-                assertEquals(expectedHeader, qeh.getAppProvidedAcceptHeader());
-            }
-
-            try (QueryExecution qe = 
conn.newQuery().query(queryString).build()) {
-                QueryExecHTTP qeh = (QueryExecHTTP)QueryExec.adapt(qe);
-                assertEquals(expectedHeader, qeh.getAppProvidedAcceptHeader());
-            }
-
-            try (QueryExecution qe = conn.query(query)) {
-                QueryExecHTTP qeh = (QueryExecHTTP)QueryExec.adapt(qe);
-                assertEquals(expectedHeader, qeh.getAppProvidedAcceptHeader());
-            }
-
-            try (QueryExecution qe = conn.newQuery().query(query).build()) {
-                QueryExecHTTP qeh = (QueryExecHTTP)QueryExec.adapt(qe);
-                assertEquals(expectedHeader, qeh.getAppProvidedAcceptHeader());
-            }
-        }
-    }
-}
diff --git 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTPHeaders.java
 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTPHeaders.java
new file mode 100644
index 0000000000..b9e3ddfd56
--- /dev/null
+++ 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdfconnection/TestRDFConnectionHTTPHeaders.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *     http://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 org.apache.jena.rdfconnection;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.sparql.exec.QueryExec;
+import org.apache.jena.sparql.exec.http.QueryExecHTTP;
+import org.apache.jena.sparql.exec.http.QueryExecutionHTTP;
+import org.apache.jena.sparql.exec.http.QueryExecutionHTTPBuilder;
+import org.junit.jupiter.api.Test;
+
+public class TestRDFConnectionHTTPHeaders {
+
+    /**
+     * Test whether connection headers are properly passed on to the query 
execution.
+     * No query is actually executed.
+     */
+    @Test void test_headers_non_parsed() {
+        try (RDFConnection conn = 
RDFConnectionRemote.service("urn:dummy-service")
+            .parseCheckSPARQL(false)
+            .acceptHeaderSelectQuery("s")
+            .acceptHeaderAskQuery("a")
+            .acceptHeaderGraph("g")
+            .acceptHeaderDataset("d")
+            .build()) {
+
+            try (QueryExecution qExec = conn.query("dummy query string")) {
+                QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+                assertEquals("s", qe.getAcceptHeaderSelect());
+                assertEquals("a", qe.getAcceptHeaderAsk());
+                assertEquals("g", qe.getAcceptHeaderDescribe());
+                assertEquals("g", qe.getAcceptHeaderConstructGraph());
+                assertEquals("d", qe.getAcceptHeaderConstructDataset());
+            }
+        }
+    }
+
+    @Test void test_headers_non_parsed_fallback() {
+        try (RDFConnection conn = 
RDFConnectionRemote.service("urn:dummy-service")
+            .parseCheckSPARQL(false)
+            .acceptHeaderQuery("f") // fallback
+            .acceptHeaderSelectQuery(null)
+            .acceptHeaderAskQuery(null)
+            .acceptHeaderGraph(null)
+            .acceptHeaderDataset(null)
+            .build()) {
+
+            try (QueryExecution qExec = conn.query("dummy query string")) {
+                QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+                assertEquals("f", qe.getAcceptHeaderSelect());
+                assertEquals("f", qe.getAcceptHeaderAsk());
+                assertEquals("f", qe.getAcceptHeaderDescribe());
+                assertEquals("f", qe.getAcceptHeaderConstructGraph());
+                assertEquals("f", qe.getAcceptHeaderConstructDataset());
+            }
+        }
+    }
+
+    @Test void test_headers_parsed_fallback() {
+        try (RDFConnection conn = 
RDFConnectionRemote.service("urn:dummy-service")
+            .acceptHeaderQuery("f") // fallback
+            .acceptHeaderSelectQuery(null)
+            .acceptHeaderAskQuery(null)
+            .acceptHeaderGraph(null)
+            .acceptHeaderDataset(null)
+            .build()) {
+
+            try (QueryExecution qExec = conn.newQuery()
+                    .query("SELECT * { ?s ?p ?o }")
+                    .build()) {
+                QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+                assertEquals("f", qe.getAcceptHeaderSelect());
+
+                assertEquals("f", qe.getAcceptHeaderAsk());
+                assertEquals("f", qe.getAcceptHeaderDescribe());
+                assertEquals("f", qe.getAcceptHeaderConstructGraph());
+                assertEquals("f", qe.getAcceptHeaderConstructDataset());
+            }
+        }
+    }
+
+    /**
+     * Setting an override-header on the builder should set all
+     * headers on the QueryExecHTTP instance to that override.
+     */
+    @Test
+    public void test_override_header_01() {
+        try (QueryExecutionHTTP qExec = QueryExecutionHTTPBuilder.create()
+                .endpoint("urn:dummy-service")
+                .queryString("SELECT * { ?s ?p ?o }")
+                .acceptHeader("o") // Override header
+                .build()) {
+            QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+            assertEquals("o", qe.getAcceptHeaderSelect());
+            assertEquals("o", qe.getAcceptHeaderAsk());
+            assertEquals("o", qe.getAcceptHeaderDescribe());
+            assertEquals("o", qe.getAcceptHeaderConstructGraph());
+            assertEquals("o", qe.getAcceptHeaderConstructDataset());
+        }
+    }
+
+    @Test
+    public void test_override_header_02() {
+        try (QueryExecutionHTTP qExec = QueryExecutionHTTPBuilder.create()
+                .endpoint("urn:dummy-service")
+                .queryString("SELECT * { ?s ?p ?o }")
+                .acceptHeader("o") // Override header first
+                .acceptHeaderGraph("g")
+                .build()) {
+            QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+            assertEquals("o", qe.getAcceptHeaderSelect());
+            assertEquals("o", qe.getAcceptHeaderAsk());
+            assertEquals("g", qe.getAcceptHeaderDescribe());
+            assertEquals("g", qe.getAcceptHeaderConstructGraph());
+            assertEquals("o", qe.getAcceptHeaderConstructDataset());
+        }
+    }
+
+    @Test
+    public void test_override_header_03() {
+        try (QueryExecutionHTTP qExec = QueryExecutionHTTPBuilder.create()
+                .endpoint("urn:dummy-service")
+                .queryString("SELECT * { ?s ?p ?o }")
+                .acceptHeaderGraph("g")
+                .acceptHeader("o") // Override header last - overrides prior 
settings.
+                .build()) {
+            QueryExecHTTP qe = (QueryExecHTTP)QueryExec.adapt(qExec);
+            assertEquals("o", qe.getAcceptHeaderSelect());
+            assertEquals("o", qe.getAcceptHeaderAsk());
+            assertEquals("o", qe.getAcceptHeaderDescribe());
+            assertEquals("o", qe.getAcceptHeaderConstructGraph());
+            assertEquals("o", qe.getAcceptHeaderConstructDataset());
+        }
+    }
+}
diff --git 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TS_RDFLink.java 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TS_RDFLink.java
index 7a5ba43b3b..248c0a3844 100644
--- a/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TS_RDFLink.java
+++ b/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TS_RDFLink.java
@@ -28,6 +28,7 @@ import org.junit.platform.suite.api.Suite;
     , TestRDFLinkLocalTxnMem.class
     , TestRDFLinkLocalMRSW.class
     , TestLibRDFLink.class
+    , TestRDFLinkHTTPHeaders.class
 })
 
 public class TS_RDFLink {}
diff --git 
a/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TestRDFLinkHTTPHeaders.java
 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TestRDFLinkHTTPHeaders.java
new file mode 100644
index 0000000000..e144f8eb27
--- /dev/null
+++ 
b/jena-rdfconnection/src/test/java/org/apache/jena/rdflink/TestRDFLinkHTTPHeaders.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *     http://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 org.apache.jena.rdflink;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.jena.sparql.exec.http.QueryExecHTTP;
+import org.apache.jena.sparql.exec.http.QueryExecHTTPBuilder;
+import org.junit.jupiter.api.Test;
+
+public class TestRDFLinkHTTPHeaders {
+
+    /**
+     * Test whether connection headers are properly passed on to the query 
execution.
+     * No query is actually executed.
+     */
+    @Test void test_headers_parsed() {
+        try (RDFLink link = RDFLinkHTTP.service("urn:dummy-service")
+            .acceptHeaderSelectQuery("s")
+            .acceptHeaderAskQuery("a")
+            .acceptHeaderGraph("g")
+            .acceptHeaderDataset("d")
+            .build()) {
+
+            try (QueryExecHTTP qe = ((QueryExecHTTPBuilder)link.newQuery())
+                    .query("SELECT * { ?s ?p ?o }")
+                    .acceptHeaderSelectQuery("x").build()) {
+                assertEquals("x", qe.getAcceptHeaderSelect());
+
+                assertEquals("a", qe.getAcceptHeaderAsk());
+                assertEquals("g", qe.getAcceptHeaderDescribe());
+                assertEquals("g", qe.getAcceptHeaderConstructGraph());
+                assertEquals("d", qe.getAcceptHeaderConstructDataset());
+            }
+
+            try (QueryExecHTTP qe = ((QueryExecHTTPBuilder)link.newQuery())
+                    .query("ASK { ?s ?p ?o }")
+                    .acceptHeaderAskQuery("x").build()) {
+                assertEquals("x", qe.getAcceptHeaderAsk());
+
+                assertEquals("s", qe.getAcceptHeaderSelect());
+                assertEquals("g", qe.getAcceptHeaderDescribe());
+                assertEquals("g", qe.getAcceptHeaderConstructGraph());
+                assertEquals("d", qe.getAcceptHeaderConstructDataset());
+            }
+
+            try (QueryExecHTTP qe = ((QueryExecHTTPBuilder)link.newQuery())
+                    .query("DESCRIBE <urn:x>")
+                    .acceptHeaderGraph("x").build()) {
+                assertEquals("x", qe.getAcceptHeaderDescribe());
+                assertEquals("x", qe.getAcceptHeaderConstructGraph());
+
+                assertEquals("s", qe.getAcceptHeaderSelect());
+                assertEquals("a", qe.getAcceptHeaderAsk());
+                assertEquals("d", qe.getAcceptHeaderConstructDataset());
+            }
+
+            try (QueryExecHTTP qe = ((QueryExecHTTPBuilder)link.newQuery())
+                    .query("CONSTRUCT WHERE { ?s ?p ?o }")
+                    .acceptHeaderGraph("x").build()) {
+                assertEquals("x", qe.getAcceptHeaderConstructGraph());
+                assertEquals("x", qe.getAcceptHeaderDescribe());
+
+                assertEquals("s", qe.getAcceptHeaderSelect());
+                assertEquals("a", qe.getAcceptHeaderAsk());
+                assertEquals("d", qe.getAcceptHeaderConstructDataset());
+            }
+
+            try (QueryExecHTTP qe = ((QueryExecHTTPBuilder)link.newQuery())
+                    .query("CONSTRUCT WHERE { GRAPH ?g { ?s ?p ?o } }")
+                    .acceptHeaderDataset("x").build()) {
+                assertEquals("x", qe.getAcceptHeaderConstructDataset());
+
+                assertEquals("s", qe.getAcceptHeaderSelect());
+                assertEquals("a", qe.getAcceptHeaderAsk());
+                assertEquals("g", qe.getAcceptHeaderDescribe());
+                assertEquals("g", qe.getAcceptHeaderConstructGraph());
+            }
+        }
+    }
+}

Reply via email to