@@ -148,7 +148,10 @@ public class ServerRuntime {
148
148
149
149
private final boolean processResponseErrors ;
150
150
151
+ /** Do not resolve relative URIs in the {@code Location} header */
151
152
private final boolean disableLocationHeaderRelativeUriResolution ;
153
+ /** Resolve relative URIs according to RFC7231 (not JAX-RS 2.0 compliant */
154
+ private final boolean rfc7231LocationHeaderRelativeUriResolution ;
152
155
153
156
/*package */ static final ExternalRequestScope <Object > NOOP_EXTERNAL_REQ_SCOPE = new ExternalRequestScope <Object >() {
154
157
@@ -254,6 +257,10 @@ private ServerRuntime(final Stage<RequestProcessingContext> requestProcessingRoo
254
257
this .disableLocationHeaderRelativeUriResolution = ServerProperties .getValue (configuration .getProperties (),
255
258
ServerProperties .LOCATION_HEADER_RELATIVE_URI_RESOLUTION_DISABLED ,
256
259
Boolean .FALSE , Boolean .class );
260
+
261
+ this .rfc7231LocationHeaderRelativeUriResolution = ServerProperties .getValue (configuration .getProperties (),
262
+ ServerProperties .LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231 ,
263
+ Boolean .FALSE , Boolean .class );
257
264
}
258
265
259
266
/**
@@ -302,7 +309,9 @@ public void run() {
302
309
// set base URI into response builder thread-local variable
303
310
// for later resolving of relative location URIs
304
311
if (!disableLocationHeaderRelativeUriResolution ) {
305
- OutboundJaxrsResponse .Builder .setBaseUri (request .getRequestUri ());
312
+ final URI uriToUse =
313
+ rfc7231LocationHeaderRelativeUriResolution ? request .getRequestUri () : request .getBaseUri ();
314
+ OutboundJaxrsResponse .Builder .setBaseUri (uriToUse );
306
315
}
307
316
308
317
final Ref <Endpoint > endpointRef = Refs .emptyRef ();
@@ -350,14 +359,17 @@ ScheduledExecutorService getBackgroundScheduler() {
350
359
* @param location location URI; value of the HTTP {@value HttpHeaders#LOCATION} response header.
351
360
* @param headers mutable map of response headers.
352
361
* @param request container request.
362
+ * @param incompatible if set to {@code true}, uri will be resolved against the request uri, not the base uri;
363
+ * this is correct against RFC7231, but does violate the JAX-RS 2.0 specs
353
364
*/
354
365
private static void ensureAbsolute (final URI location , final MultivaluedMap <String , Object > headers ,
355
- final ContainerRequest request ) {
366
+ final ContainerRequest request , final boolean incompatible ) {
356
367
if (location == null || location .isAbsolute ()) {
357
368
return ;
358
369
}
359
370
// according to RFC7231 (HTTP/1.1), this field can contain one single URI reference
360
- headers .putSingle (HttpHeaders .LOCATION , request .getRequestUri ().resolve (location ));
371
+ final URI uri = incompatible ? request .getRequestUri () : request .getBaseUri ();
372
+ headers .putSingle (HttpHeaders .LOCATION , uri .resolve (location ));
361
373
}
362
374
363
375
private static class AsyncResponderHolder implements Value <AsyncContext > {
@@ -466,7 +478,8 @@ public void process(final Throwable throwable) {
466
478
try {
467
479
response = convertResponse (exceptionResponse );
468
480
if (!runtime .disableLocationHeaderRelativeUriResolution ) {
469
- ensureAbsolute (response .getLocation (), response .getHeaders (), request );
481
+ ensureAbsolute (response .getLocation (), response .getHeaders (), request ,
482
+ runtime .rfc7231LocationHeaderRelativeUriResolution );
470
483
}
471
484
processingContext .monitoringEventBuilder ().setContainerResponse (response )
472
485
.setResponseSuccessfullyMapped (true );
@@ -659,7 +672,8 @@ private ContainerResponse writeResponse(final ContainerResponse response) {
659
672
final ContainerResponseWriter writer = request .getResponseWriter ();
660
673
661
674
if (!runtime .disableLocationHeaderRelativeUriResolution ) {
662
- ServerRuntime .ensureAbsolute (response .getLocation (), response .getHeaders (), response .getRequestContext ());
675
+ ServerRuntime .ensureAbsolute (response .getLocation (), response .getHeaders (), response .getRequestContext (),
676
+ runtime .rfc7231LocationHeaderRelativeUriResolution );
663
677
}
664
678
665
679
if (!response .hasEntity ()) {
@@ -682,7 +696,7 @@ private ContainerResponse writeResponse(final ContainerResponse response) {
682
696
public OutputStream getOutputStream (final int contentLength ) throws IOException {
683
697
if (!runtime .disableLocationHeaderRelativeUriResolution ) {
684
698
ServerRuntime .ensureAbsolute (response .getLocation (), response .getHeaders (),
685
- response .getRequestContext ());
699
+ response .getRequestContext (), runtime . rfc7231LocationHeaderRelativeUriResolution );
686
700
}
687
701
final OutputStream outputStream = writer .writeResponseStatusAndHeaders (contentLength , response );
688
702
return isHead ? null : outputStream ;
@@ -914,7 +928,8 @@ public void run() {
914
928
(response instanceof Response ) ? (Response ) response : Response .ok (response ).build ();
915
929
if (!responder .runtime .disableLocationHeaderRelativeUriResolution ) {
916
930
ServerRuntime .ensureAbsolute (jaxrsResponse .getLocation (), jaxrsResponse .getHeaders (),
917
- responder .processingContext .request ());
931
+ responder .processingContext .request (),
932
+ responder .runtime .rfc7231LocationHeaderRelativeUriResolution );
918
933
}
919
934
responder .process (new ContainerResponse (responder .processingContext .request (), jaxrsResponse ));
920
935
} catch (final Throwable t ) {
0 commit comments