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
504720e3
Commit
504720e3
authored
Dec 15, 2017
by
Craig Rueda
Committed by
Ryan Baxter
Dec 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
InputStream should always be closed after reading contents from upstreams (#2501)
* InputStream should always be closed after reading contents from upstreams
parent
07de2573
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
44 additions
and
6 deletions
+44
-6
SendResponseFilter.java
...k/cloud/netflix/zuul/filters/post/SendResponseFilter.java
+16
-4
SendResponseFilterTests.java
...ud/netflix/zuul/filters/post/SendResponseFilterTests.java
+28
-2
No files found.
spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilter.java
View file @
504720e3
...
...
@@ -191,12 +191,24 @@ public class SendResponseFilter extends ZuulFilter {
}
finally
{
/**
* Closing the wrapping InputStream itself has no effect on closing the underlying tcp connection since it's a wrapped stream. I guess for http
* keep-alive. When closing the wrapping stream it tries to reach the end of the current request, which is impossible for infinite http streams. So
* instead of closing the InputStream we close the HTTP response.
* We must ensure that the InputStream provided by our upstream pooling mechanism is ALWAYS closed
* even in the case of wrapped streams, which are supplied by pooled sources such as Apache's
* PoolingHttpClientConnectionManager. In that particular case, the underlying HTTP connection will
* be returned back to the connection pool iif either close() is explicitly called, a read
* error occurs, or the end of the underlying stream is reached. If, however a write error occurs, we will
* end up leaking a connection from the pool without an explicit close()
*
* @author Johannes Edmeier
*/
if
(
is
!=
null
)
{
try
{
is
.
close
();
}
catch
(
Exception
ex
)
{
log
.
warn
(
"Error while closing upstream input stream"
,
ex
);
}
}
try
{
Object
zuulResponse
=
RequestContext
.
getCurrentContext
()
.
get
(
"zuulResponse"
);
...
...
@@ -207,7 +219,7 @@ public class SendResponseFilter extends ZuulFilter {
// The container will close the stream for us
}
catch
(
IOException
ex
)
{
log
.
warn
(
"Error while sending response to client: "
+
ex
.
getMessage
());
log
.
warn
(
"Error while sending response to client: "
+
ex
.
getMessage
());
}
}
}
...
...
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/post/SendResponseFilterTests.java
View file @
504720e3
...
...
@@ -19,6 +19,7 @@ package org.springframework.cloud.netflix.zuul.filters.post;
import
java.io.ByteArrayInputStream
;
import
java.io.Closeable
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.lang.reflect.UndeclaredThrowableException
;
import
javax.servlet.ServletOutputStream
;
...
...
@@ -48,6 +49,7 @@ import static org.mockito.Matchers.anyInt;
import
static
org
.
mockito
.
Matchers
.
isA
;
import
static
org
.
mockito
.
Mockito
.
doThrow
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
spy
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
springframework
.
cloud
.
netflix
.
zuul
.
filters
.
support
.
FilterConstants
.
X_ZUUL_DEBUG_HEADER
;
...
...
@@ -115,13 +117,14 @@ public class SendResponseFilterTests {
}
@Test
public
void
closeResponseOutpu
s
StreamError
()
throws
Exception
{
public
void
closeResponseOutpu
t
StreamError
()
throws
Exception
{
HttpServletResponse
response
=
mock
(
HttpServletResponse
.
class
);
InputStream
mockStream
=
spy
(
new
ByteArrayInputStream
(
"Hello\n"
.
getBytes
(
"UTF-8"
)));
RequestContext
context
=
new
RequestContext
();
context
.
setRequest
(
new
MockHttpServletRequest
());
context
.
setResponse
(
response
);
context
.
setResponseDataStream
(
new
ByteArrayInputStream
(
"Hello\n"
.
getBytes
(
"UTF-8"
))
);
context
.
setResponseDataStream
(
mockStream
);
Closeable
zuulResponse
=
mock
(
Closeable
.
class
);
context
.
set
(
"zuulResponse"
,
zuulResponse
);
RequestContext
.
testSetCurrentContext
(
context
);
...
...
@@ -140,6 +143,29 @@ public class SendResponseFilterTests {
}
verify
(
zuulResponse
).
close
();
verify
(
mockStream
).
close
();
}
@Test
public
void
testCloseResponseDataStream
()
throws
Exception
{
HttpServletResponse
response
=
mock
(
HttpServletResponse
.
class
);
InputStream
mockStream
=
spy
(
new
ByteArrayInputStream
(
"Hello\n"
.
getBytes
(
"UTF-8"
)));
RequestContext
context
=
new
RequestContext
();
context
.
setRequest
(
new
MockHttpServletRequest
());
context
.
setResponse
(
response
);
context
.
setResponseDataStream
(
mockStream
);
Closeable
zuulResponse
=
mock
(
Closeable
.
class
);
context
.
set
(
"zuulResponse"
,
zuulResponse
);
RequestContext
.
testSetCurrentContext
(
context
);
when
(
response
.
getOutputStream
()).
thenReturn
(
mock
(
ServletOutputStream
.
class
));
SendResponseFilter
filter
=
new
SendResponseFilter
();
filter
.
run
();
verify
(
mockStream
).
close
();
}
private
void
runFilter
(
String
characterEncoding
,
String
content
,
boolean
streamContent
)
throws
Exception
{
...
...
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