Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-cloud-netflix
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
openSource
spring-cloud-netflix
Commits
657d9bb8
Commit
657d9bb8
authored
Oct 25, 2016
by
Ryan Baxter
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'Upstream/master' into eureka-app-name-default
parents
2dfee975
7f075d11
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
320 additions
and
192 deletions
+320
-192
RibbonCommandFactoryConfiguration.java
...cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java
+154
-0
ZuulProxyConfiguration.java
...gframework/cloud/netflix/zuul/ZuulProxyConfiguration.java
+13
-131
PreDecorationFilter.java
...k/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java
+72
-45
ZuulController.java
...pringframework/cloud/netflix/zuul/web/ZuulController.java
+3
-2
ZuulHandlerMapping.java
...gframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java
+14
-4
AdhocTestSuite.java
...ava/org/springframework/cloud/netflix/AdhocTestSuite.java
+7
-5
ServletPathZuulProxyApplicationTests.java
...ud/netflix/zuul/ServletPathZuulProxyApplicationTests.java
+40
-5
PreDecorationFilterTests.java
...ud/netflix/zuul/filters/pre/PreDecorationFilterTests.java
+17
-0
No files found.
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java
0 → 100644
View file @
657d9bb8
/*
* Copyright 2015-2016 the original author or authors.
*
* Licensed 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
.
springframework
.
cloud
.
netflix
.
zuul
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.Collections
;
import
java.util.Set
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.autoconfigure.condition.AnyNestedCondition
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.cloud.netflix.ribbon.SpringClientFactory
;
import
org.springframework.cloud.netflix.zuul.filters.ZuulProperties
;
import
org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider
;
import
org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Conditional
;
import
org.springframework.context.annotation.Configuration
;
/**
* @author Dave Syer
*
*/
public
class
RibbonCommandFactoryConfiguration
{
@Configuration
@ConditionalOnRibbonRestClient
protected
static
class
RestClientRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
RestClientRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Configuration
@ConditionalOnRibbonOkHttpClient
@ConditionalOnClass
(
name
=
"okhttp3.OkHttpClient"
)
protected
static
class
OkHttpRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
OkHttpRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Configuration
@ConditionalOnRibbonHttpClient
protected
static
class
HttpClientRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
HttpClientRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonHttpClientCondition
.
class
)
@interface
ConditionalOnRibbonHttpClient
{
}
private
static
class
OnRibbonHttpClientCondition
extends
AnyNestedCondition
{
public
OnRibbonHttpClientCondition
()
{
super
(
ConfigurationPhase
.
PARSE_CONFIGURATION
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
name
=
"zuul.ribbon.httpclient.enabled"
,
matchIfMissing
=
true
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
name
=
"ribbon.httpclient.enabled"
,
matchIfMissing
=
true
)
static
class
RibbonProperty
{}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonOkHttpClientCondition
.
class
)
@interface
ConditionalOnRibbonOkHttpClient
{
}
private
static
class
OnRibbonOkHttpClientCondition
extends
AnyNestedCondition
{
public
OnRibbonOkHttpClientCondition
()
{
super
(
ConfigurationPhase
.
PARSE_CONFIGURATION
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
"zuul.ribbon.okhttp.enabled"
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
"ribbon.okhttp.enabled"
)
static
class
RibbonProperty
{}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonRestClientCondition
.
class
)
@interface
ConditionalOnRibbonRestClient
{
}
private
static
class
OnRibbonRestClientCondition
extends
AnyNestedCondition
{
public
OnRibbonRestClientCondition
()
{
super
(
ConfigurationPhase
.
PARSE_CONFIGURATION
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
"zuul.ribbon.restclient.enabled"
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
"ribbon.restclient.enabled"
)
static
class
RibbonProperty
{}
}
}
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java
View file @
657d9bb8
...
...
@@ -16,30 +16,21 @@
package
org
.
springframework
.
cloud
.
netflix
.
zuul
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Set
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.actuate.endpoint.Endpoint
;
import
org.springframework.boot.actuate.trace.TraceRepository
;
import
org.springframework.boot.autoconfigure.condition.AnyNestedCondition
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.cloud.client.actuator.HasFeatures
;
import
org.springframework.cloud.client.discovery.DiscoveryClient
;
import
org.springframework.cloud.client.discovery.event.HeartbeatEvent
;
import
org.springframework.cloud.client.discovery.event.HeartbeatMonitor
;
import
org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent
;
import
org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent
;
import
org.springframework.cloud.netflix.ribbon.SpringClientFactory
;
import
org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer
;
import
org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper
;
import
org.springframework.cloud.netflix.zuul.filters.RouteLocator
;
...
...
@@ -49,27 +40,27 @@ import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientR
import
org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper
;
import
org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper
;
import
org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter
;
import
org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter
;
import
org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter
;
import
org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider
;
import
org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory
;
import
org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping
;
import
org.springframework.context.ApplicationEvent
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Conditional
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
/**
* @author Spencer Gibb
* @author Dave Syer
*/
@Configuration
@Import
({
RibbonCommandFactoryConfiguration
.
RestClientRibbonConfiguration
.
class
,
RibbonCommandFactoryConfiguration
.
OkHttpRibbonConfiguration
.
class
,
RibbonCommandFactoryConfiguration
.
HttpClientRibbonConfiguration
.
class
})
public
class
ZuulProxyConfiguration
extends
ZuulConfiguration
{
@SuppressWarnings
(
"rawtypes"
)
@Autowired
(
required
=
false
)
private
List
<
RibbonRequestCustomizer
>
requestCustomizers
=
Collections
.
emptyList
();
...
...
@@ -88,135 +79,27 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
@Override
@ConditionalOnMissingBean
(
RouteLocator
.
class
)
public
DiscoveryClientRouteLocator
routeLocator
()
{
return
new
DiscoveryClientRouteLocator
(
this
.
server
.
getServletPrefix
(),
this
.
discovery
,
this
.
zuulProperties
,
this
.
serviceRouteMapper
);
}
@Configuration
@ConditionalOnRibbonHttpClient
protected
static
class
HttpClientRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
HttpClientRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Configuration
@ConditionalOnRibbonRestClient
protected
static
class
RestClientRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
RestClientRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Configuration
@ConditionalOnRibbonOkHttpClient
@ConditionalOnClass
(
name
=
"okhttp3.OkHttpClient"
)
protected
static
class
OkHttpRibbonConfiguration
{
@Autowired
(
required
=
false
)
private
Set
<
ZuulFallbackProvider
>
zuulFallbackProviders
=
Collections
.
emptySet
();
@Bean
@ConditionalOnMissingBean
public
RibbonCommandFactory
<?>
ribbonCommandFactory
(
SpringClientFactory
clientFactory
,
ZuulProperties
zuulProperties
)
{
return
new
OkHttpRibbonCommandFactory
(
clientFactory
,
zuulProperties
,
zuulFallbackProviders
);
}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonHttpClientCondition
.
class
)
@interface
ConditionalOnRibbonHttpClient
{
}
private
static
class
OnRibbonHttpClientCondition
extends
AnyNestedCondition
{
public
OnRibbonHttpClientCondition
()
{
super
(
ConfigurationPhase
.
REGISTER_BEAN
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
name
=
"zuul.ribbon.httpclient.enabled"
,
matchIfMissing
=
true
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
name
=
"ribbon.httpclient.enabled"
,
matchIfMissing
=
true
)
static
class
RibbonProperty
{}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonOkHttpClientCondition
.
class
)
@interface
ConditionalOnRibbonOkHttpClient
{
}
private
static
class
OnRibbonOkHttpClientCondition
extends
AnyNestedCondition
{
public
OnRibbonOkHttpClientCondition
()
{
super
(
ConfigurationPhase
.
REGISTER_BEAN
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
"zuul.ribbon.okhttp.enabled"
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
"ribbon.okhttp.enabled"
)
static
class
RibbonProperty
{}
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OnRibbonRestClientCondition
.
class
)
@interface
ConditionalOnRibbonRestClient
{
}
private
static
class
OnRibbonRestClientCondition
extends
AnyNestedCondition
{
public
OnRibbonRestClientCondition
()
{
super
(
ConfigurationPhase
.
REGISTER_BEAN
);
}
@Deprecated
//remove in Edgware"
@ConditionalOnProperty
(
"zuul.ribbon.restclient.enabled"
)
static
class
ZuulProperty
{}
@ConditionalOnProperty
(
"ribbon.restclient.enabled"
)
static
class
RibbonProperty
{}
return
new
DiscoveryClientRouteLocator
(
this
.
server
.
getServletPrefix
(),
this
.
discovery
,
this
.
zuulProperties
,
this
.
serviceRouteMapper
);
}
// pre filters
@Bean
public
PreDecorationFilter
preDecorationFilter
(
RouteLocator
routeLocator
,
ProxyRequestHelper
proxyRequestHelper
)
{
return
new
PreDecorationFilter
(
routeLocator
,
this
.
server
.
getServletPrefix
(),
this
.
zuulProperties
,
proxyRequestHelper
);
public
PreDecorationFilter
preDecorationFilter
(
RouteLocator
routeLocator
,
ProxyRequestHelper
proxyRequestHelper
)
{
return
new
PreDecorationFilter
(
routeLocator
,
this
.
server
.
getServletPrefix
(),
this
.
zuulProperties
,
proxyRequestHelper
);
}
// route filters
@Bean
public
RibbonRoutingFilter
ribbonRoutingFilter
(
ProxyRequestHelper
helper
,
RibbonCommandFactory
<?>
ribbonCommandFactory
)
{
RibbonRoutingFilter
filter
=
new
RibbonRoutingFilter
(
helper
,
ribbonCommandFactory
,
this
.
requestCustomizers
);
RibbonRoutingFilter
filter
=
new
RibbonRoutingFilter
(
helper
,
ribbonCommandFactory
,
this
.
requestCustomizers
);
return
filter
;
}
@Bean
public
SimpleHostRoutingFilter
simpleHostRoutingFilter
(
ProxyRequestHelper
helper
,
ZuulProperties
zuulProperties
)
{
public
SimpleHostRoutingFilter
simpleHostRoutingFilter
(
ProxyRequestHelper
helper
,
ZuulProperties
zuulProperties
)
{
return
new
SimpleHostRoutingFilter
(
helper
,
zuulProperties
);
}
...
...
@@ -269,8 +152,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
}
private
static
class
ZuulDiscoveryRefreshListener
implements
ApplicationListener
<
ApplicationEvent
>
{
private
static
class
ZuulDiscoveryRefreshListener
implements
ApplicationListener
<
ApplicationEvent
>
{
private
HeartbeatMonitor
monitor
=
new
HeartbeatMonitor
();
...
...
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java
View file @
657d9bb8
...
...
@@ -50,12 +50,11 @@ public class PreDecorationFilter extends ZuulFilter {
private
ProxyRequestHelper
proxyRequestHelper
;
public
PreDecorationFilter
(
RouteLocator
routeLocator
,
String
dispatcherServletPath
,
ZuulProperties
properties
,
ProxyRequestHelper
proxyRequestHelper
)
{
public
PreDecorationFilter
(
RouteLocator
routeLocator
,
String
dispatcherServletPath
,
ZuulProperties
properties
,
ProxyRequestHelper
proxyRequestHelper
)
{
this
.
routeLocator
=
routeLocator
;
this
.
properties
=
properties
;
this
.
urlPathHelper
.
setRemoveSemicolonContent
(
properties
.
isRemoveSemicolonContent
());
this
.
urlPathHelper
.
setRemoveSemicolonContent
(
properties
.
isRemoveSemicolonContent
());
this
.
dispatcherServletPath
=
dispatcherServletPath
;
this
.
proxyRequestHelper
=
proxyRequestHelper
;
}
...
...
@@ -81,8 +80,7 @@ public class PreDecorationFilter extends ZuulFilter {
@Override
public
Object
run
()
{
RequestContext
ctx
=
RequestContext
.
getCurrentContext
();
final
String
requestURI
=
this
.
urlPathHelper
.
getPathWithinApplication
(
ctx
.
getRequest
());
final
String
requestURI
=
this
.
urlPathHelper
.
getPathWithinApplication
(
ctx
.
getRequest
());
Route
route
=
this
.
routeLocator
.
getMatchingRoute
(
requestURI
);
if
(
route
!=
null
)
{
String
location
=
route
.
getLocation
();
...
...
@@ -90,12 +88,11 @@ public class PreDecorationFilter extends ZuulFilter {
ctx
.
put
(
"requestURI"
,
route
.
getPath
());
ctx
.
put
(
"proxy"
,
route
.
getId
());
if
(!
route
.
isCustomSensitiveHeaders
())
{
this
.
proxyRequestHelper
.
addIgnoredHeaders
(
this
.
properties
.
getSensitiveHeaders
().
toArray
(
new
String
[
0
]));
this
.
proxyRequestHelper
.
addIgnoredHeaders
(
this
.
properties
.
getSensitiveHeaders
().
toArray
(
new
String
[
0
]));
}
else
{
this
.
proxyRequestHelper
.
addIgnoredHeaders
(
route
.
getSensitiveHeaders
().
toArray
(
new
String
[
0
]));
this
.
proxyRequestHelper
.
addIgnoredHeaders
(
route
.
getSensitiveHeaders
().
toArray
(
new
String
[
0
]));
}
if
(
route
.
getRetryable
()
!=
null
)
{
...
...
@@ -107,8 +104,8 @@ public class PreDecorationFilter extends ZuulFilter {
ctx
.
addOriginResponseHeader
(
"X-Zuul-Service"
,
location
);
}
else
if
(
location
.
startsWith
(
"forward:"
))
{
ctx
.
set
(
"forward.to"
,
StringUtils
.
cleanPath
(
location
.
substring
(
"forward:"
.
length
())
+
route
.
getPath
()));
ctx
.
set
(
"forward.to"
,
StringUtils
.
cleanPath
(
location
.
substring
(
"forward:"
.
length
())
+
route
.
getPath
()));
ctx
.
setRouteHost
(
null
);
return
null
;
}
...
...
@@ -119,35 +116,7 @@ public class PreDecorationFilter extends ZuulFilter {
ctx
.
addOriginResponseHeader
(
"X-Zuul-ServiceId"
,
location
);
}
if
(
this
.
properties
.
isAddProxyHeaders
())
{
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Host"
,
toHostHeader
(
ctx
.
getRequest
()));
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Port"
,
String
.
valueOf
(
ctx
.
getRequest
().
getServerPort
()));
ctx
.
addZuulRequestHeader
(
ZuulHeaders
.
X_FORWARDED_PROTO
,
ctx
.
getRequest
().
getScheme
());
String
forwardedPrefix
=
ctx
.
getRequest
().
getHeader
(
"X-Forwarded-Prefix"
);
String
contextPath
=
ctx
.
getRequest
().
getContextPath
();
String
prefix
=
StringUtils
.
hasLength
(
forwardedPrefix
)
?
forwardedPrefix
:
(
StringUtils
.
hasLength
(
contextPath
)
?
contextPath
:
null
);
if
(
StringUtils
.
hasText
(
route
.
getPrefix
()))
{
StringBuilder
newPrefixBuilder
=
new
StringBuilder
();
if
(
prefix
!=
null
)
{
if
(
prefix
.
endsWith
(
"/"
)
&&
route
.
getPrefix
().
startsWith
(
"/"
))
{
newPrefixBuilder
.
append
(
prefix
,
0
,
prefix
.
length
()
-
1
);
}
else
{
newPrefixBuilder
.
append
(
prefix
);
}
}
newPrefixBuilder
.
append
(
route
.
getPrefix
());
prefix
=
newPrefixBuilder
.
toString
();
}
if
(
prefix
!=
null
)
{
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Prefix"
,
prefix
);
}
addProxyHeaders
(
ctx
,
route
);
String
xforwardedfor
=
ctx
.
getRequest
().
getHeader
(
"X-Forwarded-For"
);
String
remoteAddr
=
ctx
.
getRequest
().
getRemoteAddr
();
if
(
xforwardedfor
==
null
)
{
...
...
@@ -174,8 +143,7 @@ public class PreDecorationFilter extends ZuulFilter {
if
(
RequestUtils
.
isZuulServletRequest
())
{
// remove the Zuul servletPath from the requestUri
log
.
debug
(
"zuulServletPath="
+
this
.
properties
.
getServletPath
());
fallBackUri
=
fallBackUri
.
replaceFirst
(
this
.
properties
.
getServletPath
(),
""
);
fallBackUri
=
fallBackUri
.
replaceFirst
(
this
.
properties
.
getServletPath
(),
""
);
log
.
debug
(
"Replaced Zuul servlet path:"
+
fallBackUri
);
}
else
{
...
...
@@ -194,11 +162,70 @@ public class PreDecorationFilter extends ZuulFilter {
return
null
;
}
private
void
addProxyHeaders
(
RequestContext
ctx
,
Route
route
)
{
HttpServletRequest
request
=
ctx
.
getRequest
();
String
host
=
toHostHeader
(
request
);
String
port
=
String
.
valueOf
(
request
.
getServerPort
());
String
proto
=
request
.
getScheme
();
if
(
hasHeader
(
request
,
"X-Forwarded-Host"
))
{
host
=
request
.
getHeader
(
"X-Forwarded-Host"
)
+
","
+
host
;
if
(!
hasHeader
(
request
,
"X-Forwarded-Port"
))
{
if
(
hasHeader
(
request
,
"X-Forwarded-Proto"
))
{
StringBuilder
builder
=
new
StringBuilder
();
for
(
String
previous
:
StringUtils
.
commaDelimitedListToStringArray
(
request
.
getHeader
(
"X-Forwarded-Proto"
)))
{
if
(
builder
.
length
()>
0
)
{
builder
.
append
(
","
);
}
builder
.
append
(
"https"
.
equals
(
previous
)
?
"443"
:
"80"
);
}
builder
.
append
(
","
).
append
(
port
);
port
=
builder
.
toString
();
}
}
else
{
port
=
request
.
getHeader
(
"X-Forwarded-Port"
)
+
","
+
port
;
}
proto
=
request
.
getHeader
(
"X-Forwarded-Proto"
)
+
","
+
proto
;
}
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Host"
,
host
);
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Port"
,
port
);
ctx
.
addZuulRequestHeader
(
ZuulHeaders
.
X_FORWARDED_PROTO
,
proto
);
addProxyPrefix
(
ctx
,
route
);
}
private
boolean
hasHeader
(
HttpServletRequest
request
,
String
name
)
{
return
StringUtils
.
hasLength
(
request
.
getHeader
(
name
));
}
private
void
addProxyPrefix
(
RequestContext
ctx
,
Route
route
)
{
String
forwardedPrefix
=
ctx
.
getRequest
().
getHeader
(
"X-Forwarded-Prefix"
);
String
contextPath
=
ctx
.
getRequest
().
getContextPath
();
String
prefix
=
StringUtils
.
hasLength
(
forwardedPrefix
)
?
forwardedPrefix
:
(
StringUtils
.
hasLength
(
contextPath
)
?
contextPath
:
null
);
if
(
StringUtils
.
hasText
(
route
.
getPrefix
()))
{
StringBuilder
newPrefixBuilder
=
new
StringBuilder
();
if
(
prefix
!=
null
)
{
if
(
prefix
.
endsWith
(
"/"
)
&&
route
.
getPrefix
().
startsWith
(
"/"
))
{
newPrefixBuilder
.
append
(
prefix
,
0
,
prefix
.
length
()
-
1
);
}
else
{
newPrefixBuilder
.
append
(
prefix
);
}
}
newPrefixBuilder
.
append
(
route
.
getPrefix
());
prefix
=
newPrefixBuilder
.
toString
();
}
if
(
prefix
!=
null
)
{
ctx
.
addZuulRequestHeader
(
"X-Forwarded-Prefix"
,
prefix
);
}
}
private
String
toHostHeader
(
HttpServletRequest
request
)
{
int
port
=
request
.
getServerPort
();
if
((
port
==
80
&&
"http"
.
equals
(
request
.
getScheme
()))
||
(
port
==
443
&&
"https"
.
equals
(
request
.
getScheme
())))
{
if
((
port
==
80
&&
"http"
.
equals
(
request
.
getScheme
()))
||
(
port
==
443
&&
"https"
.
equals
(
request
.
getScheme
())))
{
return
request
.
getServerName
();
}
else
{
}
else
{
return
request
.
getServerName
()
+
":"
+
port
;
}
}
...
...
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulController.java
View file @
657d9bb8
...
...
@@ -37,9 +37,10 @@ public class ZuulController extends ServletWrappingController {
}
@Override
protected
ModelAndView
handleRequestInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
Exception
{
public
ModelAndView
handleRequest
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
Exception
{
try
{
// We don't care about the other features of the base class, just want to
// handle the request
return
super
.
handleRequestInternal
(
request
,
response
);
}
finally
{
...
...
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java
View file @
657d9bb8
...
...
@@ -25,6 +25,8 @@ import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import
org.springframework.cloud.netflix.zuul.filters.Route
;
import
org.springframework.cloud.netflix.zuul.filters.RouteLocator
;
import
org.springframework.util.PatternMatchUtils
;
import
org.springframework.web.cors.CorsConfiguration
;
import
org.springframework.web.servlet.HandlerExecutionChain
;
import
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping
;
import
com.netflix.zuul.context.RequestContext
;
...
...
@@ -51,6 +53,16 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
setOrder
(-
200
);
}
@Override
protected
HandlerExecutionChain
getCorsHandlerExecutionChain
(
HttpServletRequest
request
,
HandlerExecutionChain
chain
,
CorsConfiguration
config
)
{
if
(
config
==
null
)
{
// Allow CORS requests to go to the backend
return
chain
;
}
return
super
.
getCorsHandlerExecutionChain
(
request
,
chain
,
config
);
}
public
void
setErrorController
(
ErrorController
errorController
)
{
this
.
errorController
=
errorController
;
}
...
...
@@ -63,10 +75,8 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
}
@Override
protected
Object
lookupHandler
(
String
urlPath
,
HttpServletRequest
request
)
throws
Exception
{
if
(
this
.
errorController
!=
null
&&
urlPath
.
equals
(
this
.
errorController
.
getErrorPath
()))
{
protected
Object
lookupHandler
(
String
urlPath
,
HttpServletRequest
request
)
throws
Exception
{
if
(
this
.
errorController
!=
null
&&
urlPath
.
equals
(
this
.
errorController
.
getErrorPath
()))
{
return
null
;
}
String
[]
ignored
=
this
.
routeLocator
.
getIgnoredPaths
().
toArray
(
new
String
[
0
]);
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java
View file @
657d9bb8
...
...
@@ -20,7 +20,11 @@ import org.junit.Ignore;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
import
org.junit.runners.Suite.SuiteClasses
;
import
org.springframework.cloud.netflix.zuul.filters.route.restclient.RestClientRibbonCommandIntegrationTests
;
import
org.springframework.cloud.netflix.feign.encoding.FeignAcceptEncodingTests
;
import
org.springframework.cloud.netflix.metrics.servo.ServoMetricReaderTests
;
import
org.springframework.cloud.netflix.ribbon.RibbonInterceptorTests
;
import
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClientTests
;
import
org.springframework.cloud.netflix.zuul.ZuulProxyConfigurationTests
;
/**
* A test suite for probing weird ordering problems in the tests.
...
...
@@ -28,10 +32,8 @@ import org.springframework.cloud.netflix.zuul.filters.route.restclient.RestClien
* @author Dave Syer
*/
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
org
.
springframework
.
cloud
.
netflix
.
zuul
.
filters
.
ProxyRequestHelperTests
.
class
,
RestClientRibbonCommandIntegrationTests
.
class
,
org
.
springframework
.
cloud
.
netflix
.
zuul
.
FormZuulProxyApplicationTests
.
class
})
@SuiteClasses
({
RibbonLoadBalancerClientTests
.
class
,
RibbonInterceptorTests
.
class
,
FeignAcceptEncodingTests
.
class
,
ServoMetricReaderTests
.
class
,
ZuulProxyConfigurationTests
.
class
})
@Ignore
public
class
AdhocTestSuite
{
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java
View file @
657d9bb8
...
...
@@ -18,6 +18,9 @@ package org.springframework.cloud.netflix.zuul;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -33,13 +36,16 @@ import org.springframework.context.annotation.Configuration;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.RequestEntity
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.annotation.DirtiesContext
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
import
org.springframework.web.bind.annotation.CrossOrigin
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.client.RestClientException
;
import
com.netflix.zuul.context.RequestContext
;
...
...
@@ -68,9 +74,38 @@ public class ServletPathZuulProxyApplicationTests {
public
void
getOnSelfViaSimpleHostRoutingFilter
()
{
this
.
routes
.
addRoute
(
"/self/**"
,
"http://localhost:"
+
this
.
port
+
"/app/local"
);
this
.
endpoint
.
reset
();
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
"http://localhost:"
+
this
.
port
+
"/app/self/1"
,
HttpMethod
.
GET
,
new
HttpEntity
<>((
Void
)
null
),
String
.
class
);
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
"Gotten 1!"
,
result
.
getBody
());
}
@Test
public
void
optionsOnRawEndpoint
()
throws
Exception
{
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
RequestEntity
.
options
(
new
URI
(
"http://localhost:"
+
this
.
port
+
"/app/local/1"
))
.
header
(
"Origin"
,
"http://localhost:9000"
).
header
(
"Access-Control-Request-Method"
,
"GET"
).
build
(),
String
.
class
);
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
"http://localhost:9000"
,
result
.
getHeaders
().
getFirst
(
"Access-Control-Allow-Origin"
));
}
@Test
public
void
optionsOnSelf
()
throws
Exception
{
this
.
routes
.
addRoute
(
"/self/**"
,
"http://localhost:"
+
this
.
port
+
"/app/local"
);
this
.
endpoint
.
reset
();
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
RequestEntity
.
options
(
new
URI
(
"http://localhost:"
+
this
.
port
+
"/app/self/1"
))
.
header
(
"Origin"
,
"http://localhost:9000"
).
header
(
"Access-Control-Request-Method"
,
"GET"
).
build
(),
String
.
class
);
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
"http://localhost:9000"
,
result
.
getHeaders
().
getFirst
(
"Access-Control-Allow-Origin"
));
}
@Test
public
void
contentOnRawEndpoint
()
throws
Exception
{
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
"http://localhost:"
+
this
.
port
+
"/app/self/1"
,
HttpMethod
.
GET
,
new
HttpEntity
<>((
Void
)
null
),
String
.
class
);
RequestEntity
.
get
(
new
URI
(
"http://localhost:"
+
this
.
port
+
"/app/local/1"
)).
build
(),
String
.
class
);
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
"Gotten 1!"
,
result
.
getBody
());
}
...
...
@@ -80,9 +115,8 @@ public class ServletPathZuulProxyApplicationTests {
this
.
routes
.
addRoute
(
new
ZuulRoute
(
"strip"
,
"/strip/**"
,
"strip"
,
"http://localhost:"
+
this
.
port
+
"/app/local"
,
false
,
false
,
null
));
this
.
endpoint
.
reset
();
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
"http://localhost:"
+
this
.
port
+
"/app/strip"
,
HttpMethod
.
GET
,
new
HttpEntity
<>((
Void
)
null
),
String
.
class
);
ResponseEntity
<
String
>
result
=
new
TestRestTemplate
().
exchange
(
"http://localhost:"
+
this
.
port
+
"/app/strip"
,
HttpMethod
.
GET
,
new
HttpEntity
<>((
Void
)
null
),
String
.
class
);
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
// Prefix not stripped to it goes to /local/strip
assertEquals
(
"Gotten strip!"
,
result
.
getBody
());
...
...
@@ -96,6 +130,7 @@ public class ServletPathZuulProxyApplicationTests {
static
class
ServletPathZuulProxyApplication
{
@RequestMapping
(
value
=
"/local/{id}"
,
method
=
RequestMethod
.
GET
)
@CrossOrigin
(
origins
=
"*"
)
public
String
get
(
@PathVariable
String
id
)
{
return
"Gotten "
+
id
+
"!"
;
}
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java
View file @
657d9bb8
...
...
@@ -104,6 +104,23 @@ public class PreDecorationFilterTests {
}
@Test
public
void
xForwardedHostAppends
()
throws
Exception
{
this
.
properties
.
setPrefix
(
"/api"
);
this
.
request
.
setRequestURI
(
"/api/foo/1"
);
this
.
request
.
setRemoteAddr
(
"5.6.7.8"
);
this
.
request
.
setServerPort
(
8080
);
this
.
request
.
addHeader
(
"X-Forwarded-Host"
,
"example.com"
);
this
.
request
.
addHeader
(
"X-Forwarded-Proto"
,
"https"
);
this
.
routeLocator
.
addRoute
(
new
ZuulRoute
(
"foo"
,
"/foo/**"
,
"foo"
,
null
,
false
,
null
,
null
));
this
.
filter
.
run
();
RequestContext
ctx
=
RequestContext
.
getCurrentContext
();
assertEquals
(
"example.com,localhost:8080"
,
ctx
.
getZuulRequestHeaders
().
get
(
"x-forwarded-host"
));
assertEquals
(
"443,8080"
,
ctx
.
getZuulRequestHeaders
().
get
(
"x-forwarded-port"
));
assertEquals
(
"https,http"
,
ctx
.
getZuulRequestHeaders
().
get
(
"x-forwarded-proto"
));
}
@Test
public
void
hostHeaderSet
()
throws
Exception
{
this
.
properties
.
setPrefix
(
"/api"
);
this
.
properties
.
setAddHostHeader
(
true
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment