@@ -93,7 +93,6 @@ public class ProxyRequestFilter implements ContainerRequestFilter
9393 private static final Logger log = LoggerFactory .getLogger (ProxyRequestFilter .class );
9494
9595 @ Inject com .atomgraph .linkeddatahub .Application system ;
96- @ Inject MediaTypes mediaTypes ;
9796 @ Inject jakarta .inject .Provider <Optional <Ontology >> ontology ;
9897 @ Context Request request ;
9998
@@ -105,17 +104,16 @@ public void filter(ContainerRequestContext requestContext) throws IOException
105104
106105 URI targetURI = targetOpt .get ();
107106
108- // do not proxy (X)HTML requests - let the downstream handler serve the standard app shell page;
109- // Saxon-JS will fetch the target RDF client-side and complete the rendering .
110- // Use proper content negotiation (same as getResponse()) so that a browser Accept header like
111- // "text/html, application/xml;q=0.9, */*;q=0.8" correctly resolves to text/html.
107+ // do not proxy requests that don't accept any RDF/SPARQL type — let the downstream handler serve the response.
108+ // Core MediaTypes contains only RDF/SPARQL types so selectVariant returns null for HTML-only Accept headers .
109+ List < MediaType > writableTypes = new ArrayList <>( getMediaTypes (). getWritable ( Model . class ));
110+ writableTypes . addAll ( getMediaTypes (). getWritable ( ResultSet . class ));
112111 List <Variant > variants = com .atomgraph .core .model .impl .Response .getVariants (
113- getMediaTypes (). getWritable ( Model . class ) ,
112+ writableTypes ,
114113 getSystem ().getSupportedLanguages (),
115114 new ArrayList <>());
116115 Variant selectedVariant = getRequest ().selectVariant (variants );
117- if (selectedVariant != null && new HTMLMediaTypePredicate ().test (selectedVariant .getMediaType ()))
118- return ;
116+ if (selectedVariant == null ) return ; // client accepts no RDF/SPARQL type
119117
120118 // strip #fragment (servers do not receive fragment identifiers)
121119 if (targetURI .getFragment () != null )
@@ -135,7 +133,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException
135133 {
136134 if (log .isDebugEnabled ()) log .debug ("Serving mapped URI from DataManager cache: {}" , targetURI );
137135 Model model = getSystem ().getDataManager ().loadModel (targetURI .toString ());
138- requestContext .abortWith (getResponse (model , Response .Status .OK ));
136+ requestContext .abortWith (getResponse (model , Response .Status .OK , selectedVariant ));
139137 return ;
140138 }
141139
@@ -153,7 +151,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException
153151 if (!description .isEmpty ())
154152 {
155153 if (log .isDebugEnabled ()) log .debug ("Serving URI from namespace ontology: {}" , targetURI );
156- requestContext .abortWith (getResponse (description , Response .Status .OK ));
154+ requestContext .abortWith (getResponse (description , Response .Status .OK , selectedVariant ));
157155 return ;
158156 }
159157 }
@@ -200,7 +198,7 @@ else if (agentContext instanceof IDTokenSecurityContext idTokenSecurityContext)
200198 {
201199 // provide the target URI as a base URI hint so ModelProvider / HtmlJsonLDReader can resolve relative references
202200 clientResponse .getHeaders ().putSingle (com .atomgraph .core .io .ModelProvider .REQUEST_URI_HEADER , targetURI .toString ());
203- requestContext .abortWith (getResponse (clientResponse ));
201+ requestContext .abortWith (getResponse (clientResponse , selectedVariant ));
204202 }
205203 }
206204 catch (MessageBodyProviderNotFoundException ex )
@@ -255,83 +253,77 @@ protected Optional<URI> resolveTargetURI(ContainerRequestContext requestContext)
255253 * Converts a client response from the proxy target into a JAX-RS response.
256254 *
257255 * @param clientResponse response from the proxy target
256+ * @param selectedVariant pre-computed variant from content negotiation
258257 * @return JAX-RS response to return to the original caller
259258 */
260- protected Response getResponse (Response clientResponse )
259+ protected Response getResponse (Response clientResponse , Variant selectedVariant )
261260 {
262261 if (clientResponse .getMediaType () == null ) return Response .status (clientResponse .getStatus ()).build ();
263- return getResponse (clientResponse , clientResponse .getStatusInfo ());
262+ return getResponse (clientResponse , clientResponse .getStatusInfo (), selectedVariant );
264263 }
265264
266265 /**
267266 * Converts a client response from the proxy target into a JAX-RS response with the given status.
268267 *
269268 * @param clientResponse response from the proxy target
270269 * @param statusType status to use in the returned response
270+ * @param selectedVariant pre-computed variant from content negotiation
271271 * @return JAX-RS response
272272 */
273- protected Response getResponse (Response clientResponse , Response .StatusType statusType )
273+ protected Response getResponse (Response clientResponse , Response .StatusType statusType , Variant selectedVariant )
274274 {
275275 MediaType formatType = new MediaType (clientResponse .getMediaType ().getType (), clientResponse .getMediaType ().getSubtype ()); // discard charset param
276276
277277 Lang lang = RDFLanguages .contentTypeToLang (formatType .toString ());
278278 if (lang != null && ResultSetReaderRegistry .isRegistered (lang ))
279279 {
280280 ResultSetRewindable results = clientResponse .readEntity (ResultSetRewindable .class );
281- return getResponse (results , statusType );
281+ return getResponse (results , statusType , selectedVariant );
282282 }
283283
284284 Model model = clientResponse .readEntity (Model .class );
285- return getResponse (model , statusType );
285+ return getResponse (model , statusType , selectedVariant );
286286 }
287287
288288 /**
289- * Builds a content-negotiated response for the given RDF model.
289+ * Builds a response for the given RDF model using a pre-computed variant .
290290 *
291291 * @param model RDF model
292292 * @param statusType response status
293+ * @param selectedVariant pre-computed variant from content negotiation
293294 * @return JAX-RS response
294295 */
295- protected Response getResponse (Model model , Response .StatusType statusType )
296+ protected Response getResponse (Model model , Response .StatusType statusType , Variant selectedVariant )
296297 {
297- List <Variant > variants = com .atomgraph .core .model .impl .Response .getVariants (
298- getMediaTypes ().getWritable (Model .class ),
299- getSystem ().getSupportedLanguages (),
300- new ArrayList <>());
301-
302298 return new com .atomgraph .core .model .impl .Response (getRequest (),
303299 model ,
304300 null ,
305301 new EntityTag (Long .toHexString (ModelUtils .hashModel (model ))),
306- variants ,
302+ selectedVariant ,
307303 new HTMLMediaTypePredicate ()).
308304 getResponseBuilder ().
309305 status (statusType ).
310306 build ();
311307 }
312308
313309 /**
314- * Builds a content-negotiated response for the given SPARQL result set.
310+ * Builds a response for the given SPARQL result set using a pre-computed variant .
315311 *
316312 * @param resultSet SPARQL result set
317313 * @param statusType response status
314+ * @param selectedVariant pre-computed variant from content negotiation
318315 * @return JAX-RS response
319316 */
320- protected Response getResponse (ResultSetRewindable resultSet , Response .StatusType statusType )
317+ protected Response getResponse (ResultSetRewindable resultSet , Response .StatusType statusType , Variant selectedVariant )
321318 {
322319 long hash = ResultSetUtils .hashResultSet (resultSet );
323320 resultSet .reset ();
324321
325- List <Variant > variants = com .atomgraph .core .model .impl .Response .getVariants (
326- getMediaTypes ().getWritable (ResultSet .class ),
327- getSystem ().getSupportedLanguages (),
328- new ArrayList <>());
329-
330322 return new com .atomgraph .core .model .impl .Response (getRequest (),
331323 resultSet ,
332324 null ,
333325 new EntityTag (Long .toHexString (hash )),
334- variants ,
326+ selectedVariant ,
335327 new HTMLMediaTypePredicate ()).
336328 getResponseBuilder ().
337329 status (statusType ).
@@ -360,12 +352,13 @@ public Optional<Ontology> getOntology()
360352
361353 /**
362354 * Returns the media types registry.
355+ * Core MediaTypes do not include (X)HTML types, which is what we want here.
363356 *
364357 * @return media types
365358 */
366359 public MediaTypes getMediaTypes ()
367360 {
368- return mediaTypes ;
361+ return new MediaTypes () ;
369362 }
370363
371364 /**
0 commit comments