-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add x-forwarded-prefix header #382
Merged
Merged
Changes from 8 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
e1d4d3c
calculated forwarded prefix using path and original uri
0f3efb1
cleanup
23c4b4a
better way
3c15406
add null checks
3d4e3ea
put back license removed by accident
272bd15
add tests for prefix and no-prefix cases
f3e7d8e
handle edge cases and switch on by default
cf5b9c2
formatting and add comment following review
74c5805
better way to strip trailing slash
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,15 +17,19 @@ | |
|
||
package org.springframework.cloud.gateway.filter.headers; | ||
|
||
import java.net.URI; | ||
import java.util.LinkedHashSet; | ||
import java.util.List; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.core.Ordered; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.server.reactive.ServerHttpRequest; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.web.server.ServerWebExchange; | ||
|
||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR; | ||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; | ||
|
||
@ConfigurationProperties("spring.cloud.gateway.x-forwarded") | ||
public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { | ||
/** default http port */ | ||
|
@@ -52,6 +56,10 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { | |
/** X-Forwarded-Proto Header */ | ||
public static final String X_FORWARDED_PROTO_HEADER = "X-Forwarded-Proto"; | ||
|
||
/** X-Forwarded-Prefix Header */ | ||
public static final String X_FORWARDED_PREFIX_HEADER = "X-Forwarded-Prefix"; | ||
|
||
|
||
/** The order of the XForwardedHeadersFilter. */ | ||
private int order = 0; | ||
|
||
|
@@ -70,6 +78,9 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { | |
/** If X-Forwarded-Proto is enabled. */ | ||
private boolean protoEnabled = true; | ||
|
||
/** If X-Forwarded-Prefix is enabled. */ | ||
private boolean prefixEnabled = true; | ||
|
||
/** If appending X-Forwarded-For as a list is enabled. */ | ||
private boolean forAppend = true; | ||
|
||
|
@@ -82,6 +93,9 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { | |
/** If appending X-Forwarded-Proto as a list is enabled. */ | ||
private boolean protoAppend = true; | ||
|
||
/** If appending X-Forwarded-Prefix as a list is enabled. */ | ||
private boolean prefixAppend = true; | ||
|
||
@Override | ||
public int getOrder() { | ||
return this.order; | ||
|
@@ -131,6 +145,14 @@ public void setProtoEnabled(boolean protoEnabled) { | |
this.protoEnabled = protoEnabled; | ||
} | ||
|
||
public boolean isPrefixEnabled() { | ||
return prefixEnabled; | ||
} | ||
|
||
public void setPrefixEnabled(boolean prefixEnabled) { | ||
this.prefixEnabled = prefixEnabled; | ||
} | ||
|
||
public boolean isForAppend() { | ||
return forAppend; | ||
} | ||
|
@@ -163,8 +185,18 @@ public void setProtoAppend(boolean protoAppend) { | |
this.protoAppend = protoAppend; | ||
} | ||
|
||
public void setPrefixAppend(boolean prefixAppend) { | ||
this.prefixAppend = prefixAppend; | ||
} | ||
|
||
public boolean isPrefixAppend() { | ||
return prefixAppend; | ||
} | ||
|
||
@Override | ||
public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) { | ||
|
||
|
||
ServerHttpRequest request = exchange.getRequest(); | ||
HttpHeaders original = input; | ||
HttpHeaders updated = new HttpHeaders(); | ||
|
@@ -187,6 +219,37 @@ public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) { | |
write(updated, X_FORWARDED_PROTO_HEADER, proto, isProtoAppend()); | ||
} | ||
|
||
if(isPrefixEnabled()) { | ||
//if the path of the url that the gw is routing to is a subset (and ending part) of the url that it is routing from then the difference is the prefix | ||
//e.g. if request original.com/prefix/get/ is routed to routedservice:8090/get then /prefix is the prefix - see XForwardedHeadersFilterTests | ||
//so first get uris, then extract paths and remove one from another if it's the ending part | ||
|
||
LinkedHashSet<URI> originalUris = exchange.getAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR); | ||
URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); | ||
|
||
if(originalUris != null && requestUri != null) { | ||
|
||
originalUris.stream().forEach(originalUri -> { | ||
|
||
if(originalUri!=null && originalUri.getPath()!=null) { | ||
String prefix = originalUri.getPath(); | ||
|
||
//strip trailing slashes before checking if request path is end of original path | ||
String originalUriPath = originalUri.getPath().substring(0, originalUri.getPath().length() - (originalUri.getPath().endsWith("/") ? 1 : 0)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to do a substring if path doesn't end with
|
||
String requestUriPath = requestUri.getPath().substring(0, requestUri.getPath().length() - (requestUri.getPath().endsWith("/") ? 1 : 0)); | ||
|
||
if(requestUriPath!=null && (originalUriPath.endsWith(requestUriPath))) { | ||
prefix = originalUriPath.replace(requestUriPath, ""); | ||
} | ||
if (prefix != null && prefix.length() > 0 && | ||
prefix.length() < originalUri.getPath().length()) { | ||
write(updated, X_FORWARDED_PREFIX_HEADER, prefix, isPrefixAppend()); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
if (isPortEnabled()) { | ||
String port = String.valueOf(request.getURI().getPort()); | ||
if (request.getURI().getPort() < 0) { | ||
|
@@ -238,4 +301,4 @@ private String toHostHeader(ServerHttpRequest request) { | |
return host + ":" + port; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment with a general overview of the algorithm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added now