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
e6943b8f
Unverified
Commit
e6943b8f
authored
Feb 07, 2018
by
Ryan Baxter
Committed by
GitHub
Feb 07, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Return content of last request when retrying failed requests (#2685)
parent
ba87fef3
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
565 additions
and
35 deletions
+565
-35
RetryableFeignLoadBalancer.java
...loud/netflix/feign/ribbon/RetryableFeignLoadBalancer.java
+17
-8
RibbonResponseStatusCodeException.java
...tflix/feign/ribbon/RibbonResponseStatusCodeException.java
+45
-0
HttpClientStatusCodeException.java
.../netflix/ribbon/apache/HttpClientStatusCodeException.java
+51
-0
HttpClientUtils.java
...ramework/cloud/netflix/ribbon/apache/HttpClientUtils.java
+50
-0
RetryableRibbonLoadBalancingHttpClient.java
...ribbon/apache/RetryableRibbonLoadBalancingHttpClient.java
+18
-13
OkHttpStatusCodeException.java
...loud/netflix/ribbon/okhttp/OkHttpStatusCodeException.java
+45
-0
RetryableOkHttpLoadBalancingClient.java
...lix/ribbon/okhttp/RetryableOkHttpLoadBalancingClient.java
+16
-5
RetryableFeignLoadBalancerTests.java
...netflix/feign/ribbon/RetryableFeignLoadBalancerTests.java
+65
-0
RibbonResponseStatusCodeExceptionTest.java
...x/feign/ribbon/RibbonResponseStatusCodeExceptionTest.java
+61
-0
HttpClientStatusCodeExceptionTest.java
...flix/ribbon/apache/HttpClientStatusCodeExceptionTest.java
+75
-0
RibbonLoadBalancingHttpClientTests.java
...lix/ribbon/apache/RibbonLoadBalancingHttpClientTests.java
+68
-9
OkHttpStatusCodeExceptionTest.java
.../netflix/ribbon/okhttp/OkHttpStatusCodeExceptionTest.java
+54
-0
No files found.
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/ribbon/RetryableFeignLoadBalancer.java
View file @
e6943b8f
...
...
@@ -22,13 +22,14 @@ import feign.Request;
import
feign.Response
;
import
java.io.IOException
;
import
java.net.URI
;
import
org.springframework.cloud.client.ServiceInstance
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedBackOffPolicyFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryListenerFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory
;
import
org.springframework.cloud.client.loadbalancer.R
etryableStatusCodeException
;
import
org.springframework.cloud.client.loadbalancer.R
ibbonRecoveryCallback
;
import
org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser
;
import
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
;
import
org.springframework.cloud.netflix.ribbon.ServerIntrospector
;
...
...
@@ -39,6 +40,7 @@ import org.springframework.retry.backoff.BackOffPolicy;
import
org.springframework.retry.backoff.NoBackOffPolicy
;
import
org.springframework.retry.policy.NeverRetryPolicy
;
import
org.springframework.retry.support.RetryTemplate
;
import
org.springframework.util.StreamUtils
;
import
com.netflix.client.DefaultLoadBalancerRetryHandler
;
import
com.netflix.client.RequestSpecificRetryHandler
;
import
com.netflix.client.config.CommonClientConfigKey
;
...
...
@@ -124,22 +126,29 @@ public class RetryableFeignLoadBalancer extends FeignLoadBalancer implements Ser
Request
feignRequest
=
null
;
//on retries the policy will choose the server and set it in the context
//extract the server and update the request being made
if
(
retryContext
instanceof
LoadBalancedRetryContext
)
{
ServiceInstance
service
=
((
LoadBalancedRetryContext
)
retryContext
).
getServiceInstance
();
if
(
service
!=
null
)
{
feignRequest
=
((
RibbonRequest
)
request
.
replaceUri
(
reconstructURIWithServer
(
new
Server
(
service
.
getHost
(),
service
.
getPort
()),
request
.
getUri
()))).
toRequest
();
if
(
retryContext
instanceof
LoadBalancedRetryContext
)
{
ServiceInstance
service
=
((
LoadBalancedRetryContext
)
retryContext
).
getServiceInstance
();
if
(
service
!=
null
)
{
feignRequest
=
((
RibbonRequest
)
request
.
replaceUri
(
reconstructURIWithServer
(
new
Server
(
service
.
getHost
(),
service
.
getPort
()),
request
.
getUri
()))).
toRequest
();
}
}
if
(
feignRequest
==
null
)
{
if
(
feignRequest
==
null
)
{
feignRequest
=
request
.
toRequest
();
}
Response
response
=
request
.
client
().
execute
(
feignRequest
,
options
);
if
(
retryPolicy
.
retryableStatusCode
(
response
.
status
()))
{
if
(
retryPolicy
.
retryableStatusCode
(
response
.
status
()))
{
byte
[]
byteArray
=
StreamUtils
.
copyToByteArray
(
response
.
body
().
asInputStream
());
response
.
close
();
throw
new
RetryableStatusCodeException
(
RetryableFeignLoadBalancer
.
this
.
getClientName
(),
response
.
status
());
throw
new
RibbonResponseStatusCodeException
(
RetryableFeignLoadBalancer
.
this
.
clientName
,
response
,
byteArray
,
request
.
getUri
());
}
return
new
RibbonResponse
(
request
.
getUri
(),
response
);
}
},
new
RibbonRecoveryCallback
<
RibbonResponse
,
Response
>()
{
@Override
protected
RibbonResponse
createResponse
(
Response
response
,
URI
uri
)
{
return
new
RibbonResponse
(
uri
,
response
);
}
});
}
...
...
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/ribbon/RibbonResponseStatusCodeException.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
feign
.
ribbon
;
import
feign.Response
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.net.URI
;
import
org.springframework.cloud.client.loadbalancer.RetryableStatusCodeException
;
import
org.springframework.util.StreamUtils
;
/**
* A {@link RetryableStatusCodeException} for {@link Response}s
* @author Ryan Baxter
*/
public
class
RibbonResponseStatusCodeException
extends
RetryableStatusCodeException
{
private
Response
response
;
public
RibbonResponseStatusCodeException
(
String
serviceId
,
Response
response
,
byte
[]
body
,
URI
uri
)
{
super
(
serviceId
,
response
.
status
(),
response
,
uri
);
this
.
response
=
Response
.
builder
().
body
(
new
ByteArrayInputStream
(
body
),
body
.
length
)
.
headers
(
response
.
headers
()).
reason
(
response
.
reason
())
.
status
(
response
.
status
()).
request
(
response
.
request
()).
build
();
}
@Override
public
Response
getResponse
()
{
return
response
;
}
}
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientStatusCodeException.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
ribbon
.
apache
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.net.URI
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.entity.BasicHttpEntity
;
import
org.apache.http.message.BasicHttpResponse
;
import
org.apache.http.util.EntityUtils
;
import
org.springframework.cloud.client.loadbalancer.RetryableStatusCodeException
;
/**
* A {@link RetryableStatusCodeException} for {@link HttpResponse}s
* @author Ryan Baxter
*/
public
class
HttpClientStatusCodeException
extends
RetryableStatusCodeException
{
private
BasicHttpResponse
response
;
public
HttpClientStatusCodeException
(
String
serviceId
,
HttpResponse
response
,
HttpEntity
entity
,
URI
uri
)
throws
IOException
{
super
(
serviceId
,
response
.
getStatusLine
().
getStatusCode
(),
response
,
uri
);
this
.
response
=
new
BasicHttpResponse
(
response
.
getStatusLine
());
this
.
response
.
setLocale
(
response
.
getLocale
());
this
.
response
.
setStatusCode
(
response
.
getStatusLine
().
getStatusCode
());
this
.
response
.
setReasonPhrase
(
response
.
getStatusLine
().
getReasonPhrase
());
this
.
response
.
setHeaders
(
response
.
getAllHeaders
());
EntityUtils
.
updateEntity
(
this
.
response
,
entity
);
}
@Override
public
HttpResponse
getResponse
()
{
return
this
.
response
;
}
}
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientUtils.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
ribbon
.
apache
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.entity.BasicHttpEntity
;
import
org.apache.http.util.EntityUtils
;
/**
* Provides basic utilities for {@link org.apache.http.client.HttpClient}
* @author Ryan Baxter
*/
public
class
HttpClientUtils
{
/**
* Creates an new {@link HttpEntity} by copying the {@link HttpEntity} from the {@link HttpResponse}.
* This method will close the response after copying the entity.
* @param response The response to create the {@link HttpEntity} from
* @return A new {@link HttpEntity}
* @throws IOException thrown if there is a problem closing the response.
*/
public
static
HttpEntity
createEntity
(
HttpResponse
response
)
throws
IOException
{
ByteArrayInputStream
is
=
new
ByteArrayInputStream
(
EntityUtils
.
toByteArray
(
response
.
getEntity
()));
BasicHttpEntity
entity
=
new
BasicHttpEntity
();
entity
.
setContent
(
is
);
entity
.
setContentLength
(
response
.
getEntity
().
getContentLength
());
if
(
CloseableHttpResponse
.
class
.
isInstance
(
response
))
{
((
CloseableHttpResponse
)
response
).
close
();
}
return
entity
;
}
}
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/RetryableRibbonLoadBalancingHttpClient.java
View file @
e6943b8f
/*
* Copyright 2013-201
7
the original author or authors.
* Copyright 2013-201
8
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.
...
...
@@ -20,7 +20,6 @@ import java.net.URI;
import
org.apache.commons.lang.BooleanUtils
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpUriRequest
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.springframework.cloud.client.ServiceInstance
;
...
...
@@ -29,13 +28,14 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryListenerFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory
;
import
org.springframework.cloud.client.loadbalancer.R
etryableStatusCodeException
;
import
org.springframework.cloud.client.loadbalancer.R
ibbonRecoveryCallback
;
import
org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser
;
import
org.springframework.cloud.client.loadbalancer.InterceptorRetryPolicy
;
import
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
;
import
org.springframework.cloud.netflix.ribbon.ServerIntrospector
;
import
org.springframework.cloud.netflix.ribbon.support.ContextAwareRequest
;
import
org.springframework.http.HttpRequest
;
import
org.springframework.retry.RecoveryCallback
;
import
org.springframework.retry.RetryCallback
;
import
org.springframework.retry.RetryContext
;
import
org.springframework.retry.RetryListener
;
...
...
@@ -116,9 +116,9 @@ public class RetryableRibbonLoadBalancingHttpClient extends RibbonLoadBalancingH
final
RequestConfig
requestConfig
=
builder
.
build
();
final
LoadBalancedRetryPolicy
retryPolicy
=
loadBalancedRetryPolicyFactory
.
create
(
this
.
getClientName
(),
this
);
RetryCallback
retryCallback
=
new
RetryCallback
()
{
RetryCallback
<
RibbonApacheHttpResponse
,
IOException
>
retryCallback
=
new
RetryCallback
<
RibbonApacheHttpResponse
,
IOException
>
()
{
@Override
public
RibbonApacheHttpResponse
doWithRetry
(
RetryContext
context
)
throws
Exception
{
public
RibbonApacheHttpResponse
doWithRetry
(
RetryContext
context
)
throws
IO
Exception
{
//on retries the policy will choose the server and set it in the context
//extract the server and update the request being made
RibbonApacheHttpRequest
newRequest
=
request
;
...
...
@@ -137,16 +137,19 @@ public class RetryableRibbonLoadBalancingHttpClient extends RibbonLoadBalancingH
HttpUriRequest
httpUriRequest
=
newRequest
.
toRequest
(
requestConfig
);
final
HttpResponse
httpResponse
=
RetryableRibbonLoadBalancingHttpClient
.
this
.
delegate
.
execute
(
httpUriRequest
);
if
(
retryPolicy
.
retryableStatusCode
(
httpResponse
.
getStatusLine
().
getStatusCode
()))
{
if
(
CloseableHttpResponse
.
class
.
isInstance
(
httpResponse
))
{
((
CloseableHttpResponse
)
httpResponse
).
close
();
}
throw
new
RetryableStatusCodeException
(
RetryableRibbonLoadBalancingHttpClient
.
this
.
clientName
,
httpResponse
.
getStatusLine
().
getStatusCode
());
throw
new
HttpClientStatusCodeException
(
RetryableRibbonLoadBalancingHttpClient
.
this
.
clientName
,
httpResponse
,
HttpClientUtils
.
createEntity
(
httpResponse
),
httpUriRequest
.
getURI
());
}
return
new
RibbonApacheHttpResponse
(
httpResponse
,
httpUriRequest
.
getURI
());
}
};
return
this
.
executeWithRetry
(
request
,
retryPolicy
,
retryCallback
);
RibbonRecoveryCallback
<
RibbonApacheHttpResponse
,
HttpResponse
>
recoveryCallback
=
new
RibbonRecoveryCallback
<
RibbonApacheHttpResponse
,
HttpResponse
>()
{
@Override
protected
RibbonApacheHttpResponse
createResponse
(
HttpResponse
response
,
URI
uri
)
{
return
new
RibbonApacheHttpResponse
(
response
,
uri
);
}
};
return
this
.
executeWithRetry
(
request
,
retryPolicy
,
retryCallback
,
recoveryCallback
);
}
@Override
...
...
@@ -159,7 +162,9 @@ public class RetryableRibbonLoadBalancingHttpClient extends RibbonLoadBalancingH
BooleanUtils
.
toBooleanDefaultIfNull
(
request
.
getContext
().
getRetryable
(),
true
);
}
private
RibbonApacheHttpResponse
executeWithRetry
(
RibbonApacheHttpRequest
request
,
LoadBalancedRetryPolicy
retryPolicy
,
RetryCallback
<
RibbonApacheHttpResponse
,
IOException
>
callback
)
throws
Exception
{
private
RibbonApacheHttpResponse
executeWithRetry
(
RibbonApacheHttpRequest
request
,
LoadBalancedRetryPolicy
retryPolicy
,
RetryCallback
<
RibbonApacheHttpResponse
,
IOException
>
callback
,
RecoveryCallback
<
RibbonApacheHttpResponse
>
recoveryCallback
)
throws
Exception
{
RetryTemplate
retryTemplate
=
new
RetryTemplate
();
boolean
retryable
=
isRequestRetryable
(
request
);
retryTemplate
.
setRetryPolicy
(
retryPolicy
==
null
||
!
retryable
?
new
NeverRetryPolicy
()
...
...
@@ -170,7 +175,7 @@ public class RetryableRibbonLoadBalancingHttpClient extends RibbonLoadBalancingH
if
(
retryListeners
!=
null
&&
retryListeners
.
length
!=
0
)
{
retryTemplate
.
setListeners
(
retryListeners
);
}
return
retryTemplate
.
execute
(
callback
);
return
retryTemplate
.
execute
(
callback
,
recoveryCallback
);
}
@Override
...
...
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpStatusCodeException.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
ribbon
.
okhttp
;
import
okhttp3.Response
;
import
okhttp3.ResponseBody
;
import
java.io.IOException
;
import
java.net.URI
;
import
org.springframework.cloud.client.loadbalancer.RetryableStatusCodeException
;
/**
* An {@link RetryableStatusCodeException} that captures a {@link Response}
* @author Ryan Baxter
*/
public
class
OkHttpStatusCodeException
extends
RetryableStatusCodeException
{
private
Response
response
;
public
OkHttpStatusCodeException
(
String
serviceId
,
Response
response
,
ResponseBody
responseBody
,
URI
uri
)
{
super
(
serviceId
,
response
.
code
(),
response
,
uri
);
this
.
response
=
new
Response
.
Builder
().
code
(
response
.
code
()).
message
(
response
.
message
()).
protocol
(
response
.
protocol
())
.
request
(
response
.
request
()).
headers
(
response
.
headers
()).
handshake
(
response
.
handshake
())
.
cacheResponse
(
response
.
cacheResponse
()).
networkResponse
(
response
.
networkResponse
())
.
priorResponse
(
response
.
priorResponse
()).
sentRequestAtMillis
(
response
.
sentRequestAtMillis
())
.
body
(
responseBody
).
build
();
}
@Override
public
Response
getResponse
()
{
return
response
;
}
}
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/okhttp/RetryableOkHttpLoadBalancingClient.java
View file @
e6943b8f
...
...
@@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.ribbon.okhttp;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.Response
;
import
okhttp3.ResponseBody
;
import
java.net.URI
;
import
org.apache.commons.lang.BooleanUtils
;
...
...
@@ -27,13 +28,14 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryListenerFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory
;
import
org.springframework.cloud.client.loadbalancer.R
etryableStatusCodeException
;
import
org.springframework.cloud.client.loadbalancer.R
ibbonRecoveryCallback
;
import
org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser
;
import
org.springframework.cloud.client.loadbalancer.InterceptorRetryPolicy
;
import
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
;
import
org.springframework.cloud.netflix.ribbon.ServerIntrospector
;
import
org.springframework.cloud.netflix.ribbon.support.ContextAwareRequest
;
import
org.springframework.http.HttpRequest
;
import
org.springframework.retry.RecoveryCallback
;
import
org.springframework.retry.RetryCallback
;
import
org.springframework.retry.RetryContext
;
import
org.springframework.retry.RetryListener
;
...
...
@@ -99,7 +101,8 @@ public class RetryableOkHttpLoadBalancingClient extends OkHttpLoadBalancingClien
}
private
OkHttpRibbonResponse
executeWithRetry
(
OkHttpRibbonRequest
request
,
LoadBalancedRetryPolicy
retryPolicy
,
RetryCallback
<
OkHttpRibbonResponse
,
Exception
>
callback
)
throws
Exception
{
RetryCallback
<
OkHttpRibbonResponse
,
Exception
>
callback
,
RecoveryCallback
<
OkHttpRibbonResponse
>
recoveryCallback
)
throws
Exception
{
RetryTemplate
retryTemplate
=
new
RetryTemplate
();
BackOffPolicy
backOffPolicy
=
loadBalancedBackOffPolicyFactory
.
createBackOffPolicy
(
this
.
getClientName
());
retryTemplate
.
setBackOffPolicy
(
backOffPolicy
==
null
?
new
NoBackOffPolicy
()
:
backOffPolicy
);
...
...
@@ -110,7 +113,7 @@ public class RetryableOkHttpLoadBalancingClient extends OkHttpLoadBalancingClien
boolean
retryable
=
isRequestRetryable
(
request
);
retryTemplate
.
setRetryPolicy
(
retryPolicy
==
null
||
!
retryable
?
new
NeverRetryPolicy
()
:
new
RetryPolicy
(
request
,
retryPolicy
,
this
,
this
.
getClientName
()));
return
retryTemplate
.
execute
(
callback
);
return
retryTemplate
.
execute
(
callback
,
recoveryCallback
);
}
@Override
...
...
@@ -143,13 +146,21 @@ public class RetryableOkHttpLoadBalancingClient extends OkHttpLoadBalancingClien
final
Request
request
=
newRequest
.
toRequest
();
Response
response
=
httpClient
.
newCall
(
request
).
execute
();
if
(
retryPolicy
.
retryableStatusCode
(
response
.
code
()))
{
ResponseBody
responseBody
=
response
.
peekBody
(
Integer
.
MAX_VALUE
);
response
.
close
();
throw
new
RetryableStatusCodeException
(
RetryableOkHttpLoadBalancingClient
.
this
.
clientName
,
response
.
code
());
throw
new
OkHttpStatusCodeException
(
RetryableOkHttpLoadBalancingClient
.
this
.
clientName
,
response
,
responseBody
,
newRequest
.
getURI
());
}
return
new
OkHttpRibbonResponse
(
response
,
newRequest
.
getUri
());
}
};
return
this
.
executeWithRetry
(
ribbonRequest
,
retryPolicy
,
retryCallback
);
return
this
.
executeWithRetry
(
ribbonRequest
,
retryPolicy
,
retryCallback
,
new
RibbonRecoveryCallback
<
OkHttpRibbonResponse
,
Response
>(){
@Override
protected
OkHttpRibbonResponse
createResponse
(
Response
response
,
URI
uri
)
{
return
new
OkHttpRibbonResponse
(
response
,
uri
);
}
});
}
@Override
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/ribbon/RetryableFeignLoadBalancerTests.java
View file @
e6943b8f
...
...
@@ -22,12 +22,17 @@ import feign.Client;
import
feign.Request
;
import
feign.Response
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.Reader
;
import
java.net.URI
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
org.junit.Assert
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.mockito.Mock
;
...
...
@@ -53,6 +58,7 @@ import org.springframework.retry.backoff.BackOffContext;
import
org.springframework.retry.backoff.BackOffInterruptedException
;
import
org.springframework.retry.backoff.BackOffPolicy
;
import
com.netflix.client.DefaultLoadBalancerRetryHandler
;
import
com.netflix.client.RequestSpecificRetryHandler
;
import
com.netflix.client.config.CommonClientConfigKey
;
import
com.netflix.client.config.IClientConfig
;
...
...
@@ -68,6 +74,7 @@ import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_AUTO
import
static
com
.
netflix
.
client
.
config
.
DefaultClientConfigImpl
.
DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
instanceOf
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
anyBoolean
;
...
...
@@ -381,6 +388,64 @@ public class RetryableFeignLoadBalancerTests {
assertEquals
(
1
,
backOffPolicyFactory
.
getCount
());
}
@Test
public
void
executeRetryFail
()
throws
Exception
{
RibbonLoadBalancerContext
lbContext
=
new
RibbonLoadBalancerContext
(
lb
,
config
);
lbContext
.
setRetryHandler
(
new
DefaultLoadBalancerRetryHandler
(
1
,
0
,
true
));
SpringClientFactory
clientFactory
=
mock
(
SpringClientFactory
.
class
);
IClientConfig
config
=
mock
(
IClientConfig
.
class
);
doReturn
(
1
).
when
(
config
).
get
(
eq
(
CommonClientConfigKey
.
MaxAutoRetries
),
anyInt
());
doReturn
(
0
).
when
(
config
).
get
(
eq
(
CommonClientConfigKey
.
MaxAutoRetriesNextServer
),
anyInt
());
doReturn
(
true
).
when
(
config
).
get
(
eq
(
CommonClientConfigKey
.
OkToRetryOnAllOperations
),
eq
(
false
));
doReturn
(
defaultConnectTimeout
).
when
(
config
).
get
(
eq
(
CommonClientConfigKey
.
ConnectTimeout
));
doReturn
(
defaultReadTimeout
).
when
(
config
).
get
(
eq
(
CommonClientConfigKey
.
ReadTimeout
));
doReturn
(
"404"
).
when
(
config
).
getPropertyAsString
(
eq
(
RibbonLoadBalancedRetryPolicy
.
RETRYABLE_STATUS_CODES
),
eq
(
""
));
doReturn
(
config
).
when
(
clientFactory
).
getClientConfig
(
eq
(
"default"
));
doReturn
(
lbContext
).
when
(
clientFactory
).
getLoadBalancerContext
(
any
(
String
.
class
));
RibbonLoadBalancedRetryPolicyFactory
loadBalancedRetryPolicyFactory
=
new
RibbonLoadBalancedRetryPolicyFactory
(
clientFactory
);
HttpRequest
springRequest
=
mock
(
HttpRequest
.
class
);
Request
feignRequest
=
Request
.
create
(
"GET"
,
"http://foo"
,
new
HashMap
<
String
,
Collection
<
String
>>(),
new
byte
[]{},
StandardCharsets
.
UTF_8
);
Client
client
=
mock
(
Client
.
class
);
FeignLoadBalancer
.
RibbonRequest
request
=
new
FeignLoadBalancer
.
RibbonRequest
(
client
,
feignRequest
,
new
URI
(
"http://foo"
));
Response
fourOFourResponse
=
Response
.
builder
().
status
(
404
).
headers
(
new
HashMap
<
String
,
Collection
<
String
>>())
.
body
(
new
Response
.
Body
()
{
//set content into response
@Override
public
Integer
length
()
{
return
"test"
.
getBytes
().
length
;
}
@Override
public
boolean
isRepeatable
()
{
return
true
;
}
@Override
public
InputStream
asInputStream
()
throws
IOException
{
return
new
ByteArrayInputStream
(
"test"
.
getBytes
());
}
@Override
public
Reader
asReader
()
throws
IOException
{
return
new
InputStreamReader
(
asInputStream
(),
"UTF-8"
);
}
@Override
public
void
close
()
throws
IOException
{
}
}).
build
();
doReturn
(
fourOFourResponse
).
when
(
client
).
execute
(
any
(
Request
.
class
),
any
(
Request
.
Options
.
class
));
MyBackOffPolicyFactory
backOffPolicyFactory
=
new
MyBackOffPolicyFactory
();
RetryableFeignLoadBalancer
feignLb
=
new
RetryableFeignLoadBalancer
(
lb
,
config
,
inspector
,
loadBalancedRetryPolicyFactory
,
backOffPolicyFactory
);
FeignLoadBalancer
.
RibbonResponse
ribbonResponse
=
feignLb
.
execute
(
request
,
null
);
verify
(
client
,
times
(
2
)).
execute
(
any
(
Request
.
class
),
any
(
Request
.
Options
.
class
));
assertEquals
(
1
,
backOffPolicyFactory
.
getCount
());
InputStream
inputStream
=
ribbonResponse
.
toResponse
().
body
().
asInputStream
();
byte
[]
buf
=
new
byte
[
100
];
int
read
=
inputStream
.
read
(
buf
);
Assert
.
assertThat
(
new
String
(
buf
,
0
,
read
),
is
(
"test"
));
}
class
MyBackOffPolicyFactory
implements
LoadBalancedBackOffPolicyFactory
,
BackOffPolicy
{
private
int
count
=
0
;
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/ribbon/RibbonResponseStatusCodeExceptionTest.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
feign
.
ribbon
;
import
feign.Request
;
import
feign.Response
;
import
java.io.ByteArrayInputStream
;
import
java.net.URI
;
import
java.nio.charset.Charset
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.util.StreamUtils
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
/**
* @author Ryan Baxter
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
RibbonResponseStatusCodeExceptionTest
{
@Test
public
void
getResponse
()
throws
Exception
{
Map
<
String
,
Collection
<
String
>>
headers
=
new
HashMap
<
String
,
Collection
<
String
>>();
List
<
String
>
fooValues
=
new
ArrayList
<
String
>();
fooValues
.
add
(
"bar"
);
headers
.
put
(
"foo"
,
fooValues
);
Request
request
=
Request
.
create
(
"GET"
,
"http://service.com"
,
new
HashMap
<
String
,
Collection
<
String
>>(),
new
byte
[]{},
Charset
.
defaultCharset
());
byte
[]
body
=
"foo"
.
getBytes
();
ByteArrayInputStream
is
=
new
ByteArrayInputStream
(
body
);
Response
response
=
Response
.
builder
().
status
(
200
).
reason
(
"Success"
).
request
(
request
).
body
(
is
,
body
.
length
).
headers
(
headers
).
build
();
RibbonResponseStatusCodeException
ex
=
new
RibbonResponseStatusCodeException
(
"service"
,
response
,
body
,
new
URI
(
request
.
url
()));
assertEquals
(
200
,
ex
.
getResponse
().
status
());
assertEquals
(
request
,
ex
.
getResponse
().
request
());
assertEquals
(
"Success"
,
ex
.
getResponse
().
reason
());
assertEquals
(
"foo"
,
StreamUtils
.
copyToString
(
ex
.
getResponse
().
body
().
asInputStream
(),
Charset
.
defaultCharset
()));
}
}
\ No newline at end of file
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/HttpClientStatusCodeExceptionTest.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
ribbon
.
apache
;
import
java.io.ByteArrayInputStream
;
import
java.net.URI
;
import
java.util.Locale
;
import
org.apache.http.Header
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.ProtocolVersion
;
import
org.apache.http.StatusLine
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.entity.BasicHttpEntity
;
import
org.apache.http.message.BasicHeader
;
import
org.apache.http.message.BasicStatusLine
;
import
org.apache.http.util.EntityUtils
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
static
org
.
junit
.
Assert
.
assertArrayEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
doReturn
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
/**
* @author Ryan Baxter
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
HttpClientStatusCodeExceptionTest
{
@Test
public
void
getResponse
()
throws
Exception
{
CloseableHttpResponse
response
=
mock
(
CloseableHttpResponse
.
class
);
doReturn
(
new
Locale
(
"en"
)).
when
(
response
).
getLocale
();
Header
foo
=
new
BasicHeader
(
"foo"
,
"bar"
);
Header
[]
headers
=
new
Header
[]{
foo
};
doReturn
(
headers
).
when
(
response
).
getAllHeaders
();
StatusLine
statusLine
=
new
BasicStatusLine
(
new
ProtocolVersion
(
"http"
,
1
,
1
),
200
,
"Success"
);
doReturn
(
statusLine
).
when
(
response
).
getStatusLine
();
BasicHttpEntity
entity
=
new
BasicHttpEntity
();
entity
.
setContent
(
new
ByteArrayInputStream
(
"foo"
.
getBytes
()));
entity
.
setContentLength
(
3
);
doReturn
(
entity
).
when
(
response
).
getEntity
();
HttpEntity
copiedEntity
=
HttpClientUtils
.
createEntity
(
response
);
HttpClientStatusCodeException
ex
=
new
HttpClientStatusCodeException
(
"service"
,
response
,
copiedEntity
,
new
URI
(
"http://service.com"
));
assertEquals
(
"en"
,
ex
.
getResponse
().
getLocale
().
toString
());
assertArrayEquals
(
headers
,
ex
.
getResponse
().
getAllHeaders
());
assertEquals
(
"Success"
,
ex
.
getResponse
().
getStatusLine
().
getReasonPhrase
());
assertEquals
(
200
,
ex
.
getResponse
().
getStatusLine
().
getStatusCode
());
assertEquals
(
"http"
,
ex
.
getResponse
().
getStatusLine
().
getProtocolVersion
().
getProtocol
());
assertEquals
(
1
,
ex
.
getResponse
().
getStatusLine
().
getProtocolVersion
().
getMajor
());
assertEquals
(
1
,
ex
.
getResponse
().
getStatusLine
().
getProtocolVersion
().
getMinor
());
assertEquals
(
"foo"
,
EntityUtils
.
toString
(
ex
.
getResponse
().
getEntity
()));
verify
(
response
,
times
(
1
)).
close
();
}
}
\ No newline at end of file
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/RibbonLoadBalancingHttpClientTests.java
View file @
e6943b8f
...
...
@@ -18,14 +18,17 @@ package org.springframework.cloud.netflix.ribbon.apache;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.net.URI
;
import
java.util.ArrayList
;
import
org.apache.http.HttpResponse
;
import
java.util.Locale
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.StatusLine
;
import
org.apache.http.client.HttpClient
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpUriRequest
;
import
org.apache.http.entity.BasicHttpEntity
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.conn.PoolingHttpClientConnectionManager
;
import
org.junit.After
;
...
...
@@ -33,6 +36,8 @@ import org.junit.Before;
import
org.junit.Test
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.ArgumentMatcher
;
import
org.mockito.invocation.InvocationOnMock
;
import
org.mockito.stubbing.Answer
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedBackOffPolicyFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryListenerFactory
;
import
org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory
;
...
...
@@ -76,6 +81,7 @@ import static org.mockito.BDDMockito.given;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
argThat
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
doAnswer
;
import
static
org
.
mockito
.
Mockito
.
doReturn
;
import
static
org
.
mockito
.
Mockito
.
doThrow
;
import
static
org
.
mockito
.
Mockito
.
mock
;
...
...
@@ -199,7 +205,6 @@ public class RibbonLoadBalancingHttpClientTests {
public
void
testNeverRetry
()
throws
Exception
{
ServerIntrospector
introspector
=
mock
(
ServerIntrospector
.
class
);
CloseableHttpClient
delegate
=
mock
(
CloseableHttpClient
.
class
);
HttpResponse
response
=
mock
(
HttpResponse
.
class
);
doThrow
(
new
IOException
(
"boom"
)).
when
(
delegate
).
execute
(
any
(
HttpUriRequest
.
class
));
DefaultClientConfigImpl
clientConfig
=
new
DefaultClientConfigImpl
();
clientConfig
.
setClientName
(
"foo"
);
...
...
@@ -214,6 +219,53 @@ public class RibbonLoadBalancingHttpClientTests {
}
}
@Test
public
void
testRetryFail
()
throws
Exception
{
int
retriesNextServer
=
0
;
int
retriesSameServer
=
1
;
boolean
retryable
=
true
;
boolean
retryOnAllOps
=
false
;
String
serviceName
=
"foo"
;
String
host
=
serviceName
;
int
port
=
80
;
HttpMethod
method
=
HttpMethod
.
GET
;
URI
uri
=
new
URI
(
"http://"
+
host
+
":"
+
port
);
CloseableHttpClient
delegate
=
mock
(
CloseableHttpClient
.
class
);
StatusLine
fourOFourStatusLine
=
mock
(
StatusLine
.
class
);
CloseableHttpResponse
fourOFourResponse
=
mock
(
CloseableHttpResponse
.
class
);
Locale
locale
=
new
Locale
(
"en"
);
doReturn
(
locale
).
when
(
fourOFourResponse
).
getLocale
();
doAnswer
(
new
Answer
()
{
@Override
public
Object
answer
(
InvocationOnMock
invocationOnMock
)
throws
Throwable
{
HttpEntity
entity
=
mock
(
HttpEntity
.
class
);
doReturn
(
new
ByteArrayInputStream
(
"test"
.
getBytes
())).
when
(
entity
).
getContent
();
return
entity
;
}
}).
when
(
fourOFourResponse
).
getEntity
();
doReturn
(
404
).
when
(
fourOFourStatusLine
).
getStatusCode
();
doReturn
(
fourOFourStatusLine
).
when
(
fourOFourResponse
).
getStatusLine
();
doReturn
(
locale
).
when
(
fourOFourResponse
).
getLocale
();
doReturn
(
fourOFourResponse
).
when
(
delegate
).
execute
(
any
(
HttpUriRequest
.
class
));
ILoadBalancer
lb
=
mock
(
ILoadBalancer
.
class
);
MyBackOffPolicyFactory
myBackOffPolicyFactory
=
new
MyBackOffPolicyFactory
();
RetryableRibbonLoadBalancingHttpClient
client
=
setupClientForRetry
(
retriesNextServer
,
retriesSameServer
,
retryable
,
retryOnAllOps
,
serviceName
,
host
,
port
,
delegate
,
lb
,
"404"
,
myBackOffPolicyFactory
);
RibbonApacheHttpRequest
request
=
mock
(
RibbonApacheHttpRequest
.
class
);
doReturn
(
uri
).
when
(
request
).
getURI
();
doReturn
(
method
).
when
(
request
).
getMethod
();
doReturn
(
request
).
when
(
request
).
withNewUri
(
any
(
URI
.
class
));
HttpUriRequest
uriRequest
=
mock
(
HttpUriRequest
.
class
);
doReturn
(
uri
).
when
(
uriRequest
).
getURI
();
doReturn
(
uriRequest
).
when
(
request
).
toRequest
(
any
(
RequestConfig
.
class
));
RibbonApacheHttpResponse
returnedResponse
=
client
.
execute
(
request
,
null
);
verify
(
delegate
,
times
(
2
)).
execute
(
any
(
HttpUriRequest
.
class
));
byte
[]
buf
=
new
byte
[
100
];
InputStream
inputStream
=
returnedResponse
.
getInputStream
();
int
read
=
inputStream
.
read
(
buf
);
assertThat
(
new
String
(
buf
,
0
,
read
),
is
(
"test"
));
}
private
RetryableRibbonLoadBalancingHttpClient
setupClientForRetry
(
int
retriesNextServer
,
int
retriesSameServer
,
boolean
retryable
,
boolean
retryOnAllOps
,
String
serviceName
,
String
host
,
int
port
,
...
...
@@ -245,7 +297,7 @@ public class RibbonLoadBalancingHttpClientTests {
doReturn
(
clientConfig
).
when
(
clientFactory
).
getClientConfig
(
eq
(
serviceName
));
LoadBalancedRetryPolicyFactory
factory
=
new
RibbonLoadBalancedRetryPolicyFactory
(
clientFactory
);
RetryableRibbonLoadBalancingHttpClient
client
=
new
RetryableRibbonLoadBalancingHttpClient
(
delegate
,
clientConfig
,
introspector
,
factory
,
loadBalancedBackOffPolicyFactory
);
introspector
,
factory
,
loadBalancedBackOffPolicyFactory
,
new
LoadBalancedRetryListenerFactory
.
DefaultRetryListenerFactory
()
);
client
.
setLoadBalancer
(
lb
);
ReflectionTestUtils
.
setField
(
client
,
"delegate"
,
delegate
);
return
client
;
...
...
@@ -340,7 +392,7 @@ public class RibbonLoadBalancingHttpClientTests {
HttpUriRequest
uriRequest
=
mock
(
HttpUriRequest
.
class
);
doReturn
(
uri
).
when
(
uriRequest
).
getURI
();
doReturn
(
uriRequest
).
when
(
request
).
toRequest
(
any
(
RequestConfig
.
class
));
RibbonApacheHttpResponse
returnedResponse
=
client
.
execute
(
request
,
null
);
client
.
execute
(
request
,
null
);
verify
(
delegate
,
times
(
3
)).
execute
(
any
(
HttpUriRequest
.
class
));
verify
(
lb
,
times
(
2
)).
chooseServer
(
eq
(
serviceName
));
assertEquals
(
2
,
myBackOffPolicyFactory
.
getCount
());
...
...
@@ -393,7 +445,7 @@ public class RibbonLoadBalancingHttpClientTests {
ServerIntrospector
introspector
=
mock
(
ServerIntrospector
.
class
);
RibbonCommandContext
context
=
new
RibbonCommandContext
(
serviceName
,
method
.
toString
(),
uri
.
toString
(),
false
,
new
LinkedMultiValueMap
<
String
,
String
>(),
new
LinkedMultiValueMap
<
String
,
String
>(),
new
ByteArrayInputStream
(
new
String
(
"bar"
)
.
getBytes
()),
new
ByteArrayInputStream
(
"bar"
.
getBytes
()),
new
ArrayList
<
RibbonRequestCustomizer
>());
RibbonApacheHttpRequest
request
=
new
RibbonApacheHttpRequest
(
context
);
CloseableHttpClient
delegate
=
mock
(
CloseableHttpClient
.
class
);
...
...
@@ -404,7 +456,7 @@ public class RibbonLoadBalancingHttpClientTests {
doReturn
(
response
).
when
(
delegate
).
execute
(
any
(
HttpUriRequest
.
class
));
RibbonLoadBalancingHttpClient
client
=
new
RibbonLoadBalancingHttpClient
(
delegate
,
clientConfig
,
introspector
);
RibbonApacheHttpResponse
returnedResponse
=
client
.
execute
(
request
,
null
);
client
.
execute
(
request
,
null
);
verify
(
response
,
times
(
0
)).
close
();
verify
(
delegate
,
times
(
1
)).
execute
(
argThat
(
new
ArgumentMatcher
<
HttpUriRequest
>()
{
@Override
...
...
@@ -506,10 +558,17 @@ public class RibbonLoadBalancingHttpClientTests {
URI
uri
=
new
URI
(
"http://"
+
host
+
":"
+
port
);
CloseableHttpClient
delegate
=
mock
(
CloseableHttpClient
.
class
);
final
CloseableHttpResponse
response
=
mock
(
CloseableHttpResponse
.
class
);
Locale
locale
=
new
Locale
(
"en"
);
doReturn
(
locale
).
when
(
response
).
getLocale
();
StatusLine
statusLine
=
mock
(
StatusLine
.
class
);
doReturn
(
200
).
when
(
statusLine
).
getStatusCode
();
doReturn
(
statusLine
).
when
(
response
).
getStatusLine
();
final
CloseableHttpResponse
fourOFourResponse
=
mock
(
CloseableHttpResponse
.
class
);
doReturn
(
locale
).
when
(
fourOFourResponse
).
getLocale
();
BasicHttpEntity
entity
=
new
BasicHttpEntity
();
entity
.
setContentLength
(
5
);
entity
.
setContent
(
new
ByteArrayInputStream
(
"error"
.
getBytes
()));
doReturn
(
entity
).
when
(
fourOFourResponse
).
getEntity
();
StatusLine
fourOFourStatusLine
=
mock
(
StatusLine
.
class
);
doReturn
(
404
).
when
(
fourOFourStatusLine
).
getStatusCode
();
doReturn
(
fourOFourStatusLine
).
when
(
fourOFourResponse
).
getStatusLine
();
...
...
@@ -525,7 +584,7 @@ public class RibbonLoadBalancingHttpClientTests {
HttpUriRequest
uriRequest
=
mock
(
HttpUriRequest
.
class
);
doReturn
(
uri
).
when
(
uriRequest
).
getURI
();
doReturn
(
uriRequest
).
when
(
request
).
toRequest
(
any
(
RequestConfig
.
class
));
RibbonApacheHttpResponse
returnedResponse
=
client
.
execute
(
request
,
null
);
client
.
execute
(
request
,
null
);
verify
(
fourOFourResponse
,
times
(
1
)).
close
();
verify
(
delegate
,
times
(
2
)).
execute
(
any
(
HttpUriRequest
.
class
));
verify
(
lb
,
times
(
1
)).
chooseServer
(
eq
(
serviceName
));
...
...
@@ -777,7 +836,7 @@ public class RibbonLoadBalancingHttpClientTests {
count
++;
}
public
int
getCount
()
{
int
getCount
()
{
return
count
;
}
...
...
@@ -811,7 +870,7 @@ public class RibbonLoadBalancingHttpClientTests {
}};
}
public
int
getOnError
()
{
int
getOnError
()
{
return
onError
;
}
}
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpStatusCodeExceptionTest.java
0 → 100644
View file @
e6943b8f
/*
* Copyright 2013-2018 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
.
ribbon
.
okhttp
;
import
okhttp3.Headers
;
import
okhttp3.MediaType
;
import
okhttp3.Protocol
;
import
okhttp3.Request
;
import
okhttp3.Response
;
import
okhttp3.ResponseBody
;
import
java.net.URI
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
/**
* @author Ryan Baxter
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
OkHttpStatusCodeExceptionTest
{
@Test
public
void
getResponse
()
throws
Exception
{
Headers
headers
=
new
Headers
.
Builder
().
add
(
"foo"
,
"bar"
).
build
();
Response
response
=
new
Response
.
Builder
().
code
(
200
).
headers
(
headers
).
code
(
200
).
message
(
"Success"
)
.
body
(
ResponseBody
.
create
(
MediaType
.
parse
(
"text/plain"
),
"foo"
)).
protocol
(
Protocol
.
HTTP_1_1
)
.
request
(
new
Request
.
Builder
().
url
(
"http://service.com"
).
build
()).
build
();
ResponseBody
body
=
response
.
peekBody
(
Integer
.
MAX_VALUE
);
OkHttpStatusCodeException
ex
=
new
OkHttpStatusCodeException
(
"service"
,
response
,
body
,
new
URI
(
"http://service.com"
));
assertEquals
(
headers
,
ex
.
getResponse
().
headers
());
assertEquals
(
200
,
ex
.
getResponse
().
code
());
assertEquals
(
"Success"
,
ex
.
getResponse
().
message
());
assertEquals
(
"foo"
,
ex
.
getResponse
().
body
().
string
());
assertEquals
(
Protocol
.
HTTP_1_1
,
ex
.
getResponse
().
protocol
());
}
}
\ No newline at end of file
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