Skip to content

Commit 4f96edc

Browse files
committed
Computed original reference according to the proxy forwarding. Issue #1191
1 parent e4dc905 commit 4f96edc

File tree

9 files changed

+94
-49
lines changed

9 files changed

+94
-49
lines changed

Diff for: modules/org.restlet.ext.jetty/src/org/restlet/ext/jetty/JettyServerHelper.java

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
import javax.servlet.ServletException;
3434

35-
import org.eclipse.jetty.http.HttpGenerator;
3635
import org.eclipse.jetty.io.ArrayByteBufferPool;
3736
import org.eclipse.jetty.io.ByteBufferPool;
3837
import org.eclipse.jetty.server.ConnectionFactory;

Diff for: modules/org.restlet.ext.nio/src/org/restlet/ext/nio/internal/request/HttpInboundRequest.java

+19-26
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.restlet.engine.header.WarningReader;
6161
import org.restlet.engine.security.AuthenticatorUtils;
6262
import org.restlet.engine.util.DateUtils;
63+
import org.restlet.engine.util.ReferenceUtils;
6364
import org.restlet.ext.nio.internal.connection.Connection;
6465
import org.restlet.util.Series;
6566

@@ -746,16 +747,16 @@ public void setHeaders(Series<Header> headers) {
746747
} else {
747748
// IPv6 address handling.
748749
//
749-
// Two possible cases, host == "[::1]:8182" --using the 8182
750-
// port. host == "[::1]" ------ using the default port 80.
750+
// Two possible cases:
751+
// - host == "[::1]:8182" --using the 8182 port.
752+
// - host == "[::1]" ------ using the default port 80.
751753
//
752754
// For IPv6 address, we use ']' to separate the domain and the
753755
// port, because it's unique.
754756
if (rightSquareBracketIndex + 1 < host.length()) {
755757
// Using specified port
756758
hostDomain = host.substring(0, rightSquareBracketIndex + 1);
757-
hostPort = Integer.valueOf(host
758-
.substring(rightSquareBracketIndex + 2));
759+
hostPort = Integer.valueOf(host.substring(rightSquareBracketIndex + 2));
759760
} else if (rightSquareBracketIndex + 1 == host.length()) {
760761
// Must be using default port 80,
761762
hostDomain = host;
@@ -767,15 +768,11 @@ public void setHeaders(Series<Header> headers) {
767768
+ hostDomain + ", hostPort: " + hostPort);
768769
}
769770
} else {
770-
Protocol serverProtocol = getConnection().getHelper().getHelped()
771-
.getProtocols().get(0);
772-
773-
if (!Protocol.SIP.getSchemeName().equals(
774-
serverProtocol.getSchemeName())
775-
&& !Protocol.SIPS.getSchemeName().equals(
776-
serverProtocol.getSchemeName())) {
777-
Context.getCurrentLogger()
778-
.info("Couldn't find the mandatory \"Host\" HTTP header. Falling back to the IP address.");
771+
Protocol serverProtocol = getConnection().getHelper().getHelped().getProtocols().get(0);
772+
773+
if (!Protocol.SIP.getSchemeName().equals(serverProtocol.getSchemeName())
774+
&& !Protocol.SIPS.getSchemeName().equals(serverProtocol.getSchemeName())) {
775+
Context.getCurrentLogger().info("Couldn't find the mandatory \"Host\" HTTP header. Falling back to the IP address.");
779776
hostDomain = getConnection().getAddress();
780777
hostPort = getConnection().getPort();
781778

@@ -784,8 +781,7 @@ public void setHeaders(Series<Header> headers) {
784781
}
785782

786783
if (hostPort == -1) {
787-
hostPort = getConnection().getHelper().getHelped()
788-
.getActualPort();
784+
hostPort = getConnection().getHelper().getHelped().getActualPort();
789785
}
790786

791787
if (hostPort == -1) {
@@ -795,8 +791,7 @@ public void setHeaders(Series<Header> headers) {
795791
}
796792

797793
// Set the host reference
798-
Protocol protocol = getConnection().getHelper().getHelped()
799-
.getProtocols().get(0);
794+
Protocol protocol = getConnection().getHelper().getHelped().getProtocols().get(0);
800795
StringBuilder sb = new StringBuilder();
801796
sb.append(protocol.getSchemeName()).append("://");
802797
sb.append(hostDomain);
@@ -814,20 +809,18 @@ public void setHeaders(Series<Header> headers) {
814809
if (getResourceRef().isRelative()) {
815810
// Take care of the "/" between the host part and the segments.
816811
if (!resourceUri.startsWith("/")) {
817-
setResourceRef(new Reference(getHostRef().toString() + "/"
818-
+ resourceUri));
812+
setResourceRef(new Reference(getHostRef().toString() + "/" + resourceUri));
819813
} else {
820-
setResourceRef(new Reference(getHostRef().toString()
821-
+ resourceUri));
814+
setResourceRef(new Reference(getHostRef().toString() + resourceUri));
822815
}
823816
}
824817

825-
setOriginalRef(getResourceRef().getTargetRef());
818+
setOriginalRef(ReferenceUtils.getOriginalRef(getResourceRef(), headers));
826819
}
827820

828821
// Set the request date
829-
String dateHeader = (getHeaders() == null) ? null : getHeaders()
830-
.getFirstValue(HeaderConstants.HEADER_DATE, true);
822+
String dateHeader = (getHeaders() == null) ? null :
823+
getHeaders().getFirstValue(HeaderConstants.HEADER_DATE, true);
831824
Date date = null;
832825
if (dateHeader != null) {
833826
date = DateUtils.parse(dateHeader);
@@ -840,8 +833,8 @@ public void setHeaders(Series<Header> headers) {
840833
setDate(date);
841834

842835
// Set the max forwards
843-
String maxForwardsHeader = (getHeaders() == null) ? null : getHeaders()
844-
.getFirstValue(HeaderConstants.HEADER_MAX_FORWARDS, true);
836+
String maxForwardsHeader = (getHeaders() == null) ? null :
837+
getHeaders().getFirstValue(HeaderConstants.HEADER_MAX_FORWARDS, true);
845838
if (maxForwardsHeader != null) {
846839
try {
847840
setMaxForwards(Integer.parseInt(maxForwardsHeader));

Diff for: modules/org.restlet.ext.sip/src/org/restlet/ext/sip/internal/SipInboundRequest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.restlet.engine.header.WarningReader;
5959
import org.restlet.engine.security.AuthenticatorUtils;
6060
import org.restlet.engine.util.DateUtils;
61+
import org.restlet.engine.util.ReferenceUtils;
6162
import org.restlet.ext.nio.internal.connection.Connection;
6263
import org.restlet.ext.nio.internal.request.InboundRequest;
6364
import org.restlet.ext.sip.Address;
@@ -1145,7 +1146,7 @@ public void setHeaders(Series<Header> headers) {
11451146
}
11461147
}
11471148

1148-
setOriginalRef(getResourceRef().getTargetRef());
1149+
setOriginalRef(ReferenceUtils.getOriginalRef(getResourceRef(), headers));
11491150
}
11501151

11511152
// Set the request date

Diff for: modules/org.restlet.test/src/org/restlet/test/data/ReferenceTestCase.java

+15
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@
2828
import java.util.List;
2929

3030
import org.restlet.data.Form;
31+
import org.restlet.data.Header;
3132
import org.restlet.data.Protocol;
3233
import org.restlet.data.Reference;
34+
import org.restlet.engine.header.HeaderConstants;
35+
import org.restlet.engine.util.ReferenceUtils;
3336
import org.restlet.test.RestletTestCase;
37+
import org.restlet.util.Series;
3438

3539
/**
3640
* Test {@link org.restlet.data.Reference}.
@@ -199,6 +203,17 @@ public void testMatrix() {
199203
newForm.add("c", "4");
200204
assertEquals("a=1;b=2;c=4", newForm.getMatrixString());
201205
}
206+
207+
public void testOriginalRef() {
208+
Reference ref = new Reference("http://localhost/test");
209+
Series<Header> headers = new Series<>(Header.class);
210+
headers.add(HeaderConstants.HEADER_X_FORWARDED_PROTO, "HTTPS");
211+
headers.add(HeaderConstants.HEADER_X_FORWARDED_PORT, "123");
212+
213+
Reference originalRef = ReferenceUtils.getOriginalRef(ref, headers);
214+
assertEquals(originalRef.getSchemeProtocol(), Protocol.HTTPS);
215+
assertEquals(originalRef.getHostPort(), 123);
216+
}
202217

203218
/**
204219
* Test the computation of parent references, for absolute and relative

Diff for: modules/org.restlet/src/org/restlet/engine/adapter/HttpRequest.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.restlet.data.Cookie;
4242
import org.restlet.data.Header;
4343
import org.restlet.data.Method;
44+
import org.restlet.data.Protocol;
4445
import org.restlet.data.Range;
4546
import org.restlet.data.RecipientInfo;
4647
import org.restlet.data.Reference;
@@ -58,6 +59,7 @@
5859
import org.restlet.engine.header.WarningReader;
5960
import org.restlet.engine.security.AuthenticatorUtils;
6061
import org.restlet.engine.util.DateUtils;
62+
import org.restlet.engine.util.ReferenceUtils;
6163
import org.restlet.representation.Representation;
6264
import org.restlet.util.Series;
6365

@@ -164,8 +166,7 @@ public HttpRequest(Context context, ServerCall httpCall) {
164166
sb.append(httpCall.getProtocol().getSchemeName()).append("://");
165167
sb.append(httpCall.getHostDomain());
166168
if ((httpCall.getHostPort() != -1)
167-
&& (httpCall.getHostPort() != httpCall.getProtocol()
168-
.getDefaultPort())) {
169+
&& (httpCall.getHostPort() != httpCall.getProtocol().getDefaultPort())) {
169170
sb.append(':').append(httpCall.getHostPort());
170171
}
171172
setHostRef(sb.toString());
@@ -185,12 +186,11 @@ public HttpRequest(Context context, ServerCall httpCall) {
185186
}
186187
}
187188

188-
setOriginalRef(getResourceRef().getTargetRef());
189+
setOriginalRef(ReferenceUtils.getOriginalRef(getResourceRef(), httpCall.getRequestHeaders()));
189190
}
190191

191192
// Set the request date
192-
String dateHeader = httpCall.getRequestHeaders().getFirstValue(
193-
HeaderConstants.HEADER_DATE, true);
193+
String dateHeader = httpCall.getRequestHeaders().getFirstValue(HeaderConstants.HEADER_DATE, true);
194194
Date date = null;
195195
if (dateHeader != null) {
196196
date = DateUtils.parse(dateHeader);

Diff for: modules/org.restlet/src/org/restlet/engine/header/HeaderConstants.java

+5
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ public final class HeaderConstants {
193193

194194
public static final String HEADER_X_FORWARDED_FOR = "X-Forwarded-For";
195195

196+
public static final String HEADER_X_FORWARDED_PORT = "X-Forwarded-Port";
197+
198+
public static final String HEADER_X_FORWARDED_PROTO = "X-Forwarded-Proto";
199+
200+
196201
public static final String HEADER_X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
197202

198203
// -------------------------

Diff for: modules/org.restlet/src/org/restlet/engine/local/DirectoryServerResource.java

+12-13
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,16 @@ public void doInit() throws ResourceException {
186186
}
187187

188188
// Update the member variables
189-
this.relativePart = getReference().getRemainingPart(false, false);
190189
setNegotiated(this.directory.isNegotiatingContent());
191-
192-
// Restore the original URI in case the call has been tunneled.
193-
if ((getApplication() != null)
194-
&& getApplication().getTunnelService().isExtensionsTunnel()) {
195-
this.originalRef = getOriginalRef();
196-
197-
if (this.originalRef != null) {
198-
this.originalRef.setBaseRef(getReference().getBaseRef());
190+
this.relativePart = getReference().getRemainingPart(false, false);
191+
this.originalRef = getOriginalRef();
192+
if (this.originalRef != null) {
193+
// Restore the original URI in case the call has been tunneled.
194+
if ((getApplication() != null)
195+
&& getApplication().getTunnelService().isExtensionsTunnel()) {
196+
Reference originalBaseRef = new Reference(this.originalRef);
197+
originalBaseRef.setPath(getReference().getBaseRef().getPath());
198+
this.originalRef.setBaseRef(originalBaseRef);
199199
this.relativePart = this.originalRef.getRemainingPart();
200200
}
201201
}
@@ -729,12 +729,11 @@ public Representation handle() {
729729
}
730730

731731
// detected a directory, but the current reference lacks the trailing "/", let's redirect.
732-
Reference directoryReference = (this.originalRef != null) ? this.originalRef : getReference();
733-
732+
Reference directoryReference = (this.originalRef != null) ? this.originalRef : getReference().getTargetRef();
734733
if (directoryReference.hasQuery()) {
735-
redirectSeeOther(directoryReference.getPath() + "/?" + directoryReference.getQuery());
734+
redirectSeeOther(directoryReference.toString(false, false) + "/?" + directoryReference.getQuery());
736735
} else {
737-
redirectSeeOther(directoryReference.getPath() + "/");
736+
redirectSeeOther(directoryReference.toString(false, false) + "/");
738737
}
739738

740739
return null;

Diff for: modules/org.restlet/src/org/restlet/engine/util/ReferenceUtils.java

+35-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@
2525
package org.restlet.engine.util;
2626

2727
import org.restlet.Request;
28+
import org.restlet.data.Header;
29+
import org.restlet.data.Protocol;
2830
import org.restlet.data.Reference;
31+
import org.restlet.engine.header.HeaderConstants;
2932
import org.restlet.engine.security.AuthenticatorUtils;
33+
import org.restlet.util.Series;
3034

3135
/**
3236
* Utilities related to URI references.
@@ -45,8 +49,8 @@ public class ReferenceUtils {
4549
* @return The absolute request URI.
4650
*/
4751
public static Reference update(Reference resourceRef, Request request) {
48-
Reference result = resourceRef.isAbsolute() ? resourceRef : resourceRef
49-
.getTargetRef();
52+
Reference result = resourceRef.isAbsolute() ? resourceRef :
53+
resourceRef.getTargetRef();
5054

5155
// Optionally update the request before formatting its URI
5256
result = AuthenticatorUtils.updateReference(result,
@@ -89,6 +93,35 @@ public static String format(Reference resourceRef, boolean isProxied,
8993
return result;
9094
}
9195

96+
/**
97+
* Returns the original reference especially by detecting potential proxy forwardings.
98+
*
99+
* @param resourceRef
100+
* The request's resource reference.
101+
* @param headers
102+
* The set of request's headers.
103+
* @return The original reference.
104+
*/
105+
public static Reference getOriginalRef(Reference resourceRef, Series<Header> headers) {
106+
Reference originalRef = resourceRef.getTargetRef();
107+
108+
if (headers == null) {
109+
return originalRef;
110+
}
111+
112+
String value = headers.getFirstValue(HeaderConstants.HEADER_X_FORWARDED_PORT);
113+
if (value != null) {
114+
originalRef.setHostPort(Integer.parseInt(value));
115+
}
116+
117+
value = headers.getFirstValue(HeaderConstants.HEADER_X_FORWARDED_PROTO);
118+
if (value != null) {
119+
originalRef.setScheme(value);
120+
}
121+
122+
return originalRef;
123+
}
124+
92125
/**
93126
* Constructor.
94127
*/

Diff for: modules/org.restlet/src/org/restlet/engine/util/TemplateDispatcher.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public int beforeHandle(Request request, Response response) {
8484
request.setResourceRef(template.format(request, response));
8585
}
8686

87-
request.setOriginalRef(request.getResourceRef().getTargetRef());
87+
request.setOriginalRef(ReferenceUtils.getOriginalRef(request.getResourceRef(), request.getHeaders()));
8888
return CONTINUE;
8989
}
9090

0 commit comments

Comments
 (0)