1717package org .springframework .ws .transport .http ;
1818
1919import java .io .ByteArrayInputStream ;
20+ import java .io .ByteArrayOutputStream ;
21+ import java .io .IOException ;
2022import java .io .InputStream ;
23+ import java .io .OutputStream ;
24+ import java .net .URI ;
25+ import java .net .URISyntaxException ;
26+ import java .nio .charset .StandardCharsets ;
2127import java .util .Collections ;
28+ import java .util .Iterator ;
29+ import java .util .List ;
30+ import java .util .Map ;
2231import java .util .Random ;
32+ import java .util .zip .GZIPOutputStream ;
2333
2434import org .apache .commons .io .IOUtils ;
2535import org .apache .commons .io .input .BoundedInputStream ;
2636import org .junit .jupiter .api .Test ;
37+ import org .junit .jupiter .params .ParameterizedTest ;
38+ import org .junit .jupiter .params .provider .ValueSource ;
2739import org .mockito .ArgumentCaptor ;
2840
41+ import org .springframework .core .io .ClassPathResource ;
42+ import org .springframework .core .io .Resource ;
43+ import org .springframework .util .MultiValueMap ;
44+ import org .springframework .util .StreamUtils ;
2945import org .springframework .ws .WebServiceMessage ;
3046import org .springframework .ws .WebServiceMessageFactory ;
3147
3551import static org .mockito .Mockito .when ;
3652
3753/**
54+ * Tests for {@link AbstractHttpSenderConnection}.
55+ *
3856 * @author Andreas Veithen
57+ * @author Stephane Nicoll
3958 */
4059class AbstractHttpSenderConnectionTests {
4160
@@ -45,15 +64,17 @@ class AbstractHttpSenderConnectionTests {
4564 * @param chunking Specifies whether the test should simulate a response with chunking
4665 * enabled.
4766 */
48- private void testSupportsStreaming (boolean chunking ) throws Exception {
67+ @ ParameterizedTest
68+ @ ValueSource (booleans = { true , false })
69+ void connectionSupportsStreaming (boolean chunking ) throws Exception {
4970 byte [] content = new byte [16 * 1024 ];
5071 new Random ().nextBytes (content );
5172 BoundedInputStream rawInputStream = BoundedInputStream .builder ()
5273 .setInputStream (new ByteArrayInputStream (content ))
5374 .get ();
5475 AbstractHttpSenderConnection connection = spy (AbstractHttpSenderConnection .class );
5576 when (connection .getResponseCode ()).thenReturn (200 );
56- // Simulate response with chunking enabled
77+ // Simulate response with chunking if necessary
5778 when (connection .getResponseContentLength ()).thenReturn (chunking ? -1L : content .length );
5879 when (connection .getRawResponseInputStream ()).thenReturn (rawInputStream );
5980 when (connection .getResponseHeaders (any ())).thenReturn (Collections .emptyIterator ());
@@ -72,13 +93,86 @@ private void testSupportsStreaming(boolean chunking) throws Exception {
7293 }
7394
7495 @ Test
75- void testSupportsStreamingWithChunkingEnabled () throws Exception {
76- testSupportsStreaming (true );
96+ void gzipResponseIsDecodedIfNecessary () throws IOException {
97+ ClassPathResource response = new ClassPathResource ("soapRequest.xml" , getClass ());
98+ long responseSize = StreamUtils .copyToByteArray (response .getInputStream ()).length ;
99+ MultiValueMap <String , String > responseHeaders = MultiValueMap .fromSingleValue (
100+ Map .of (HttpTransportConstants .HEADER_CONTENT_ENCODING , HttpTransportConstants .CONTENT_ENCODING_GZIP ,
101+ HttpTransportConstants .HEADER_CONTENT_LENGTH , String .valueOf (responseSize )));
102+ AbstractHttpSenderConnection connection = new TestHttpClientConnection (
103+ new ByteArrayInputStream (compress (response )), responseHeaders );
104+ assertThat (connection .hasResponse ()).isTrue ();
105+ assertThat (StreamUtils .copyToString (connection .getResponseInputStream (), StandardCharsets .UTF_8 ))
106+ .isEqualTo (StreamUtils .copyToString (response .getInputStream (), StandardCharsets .UTF_8 ));
77107 }
78108
79- @ Test
80- void testSupportsStreamingWithChunkingDisabled () throws Exception {
81- testSupportsStreaming (false );
109+ private byte [] compress (Resource resource ) throws IOException {
110+ ByteArrayOutputStream out = new ByteArrayOutputStream ();
111+ try (InputStream in = resource .getInputStream (); GZIPOutputStream gzipOut = new GZIPOutputStream (out );) {
112+ StreamUtils .copy (in , gzipOut );
113+ }
114+ return out .toByteArray ();
115+ }
116+
117+ private static final class TestHttpClientConnection extends AbstractHttpSenderConnection {
118+
119+ private final InputStream rawResponseInputStream ;
120+
121+ private final MultiValueMap <String , String > responseHeaders ;
122+
123+ public TestHttpClientConnection (InputStream rawResponseInputStream ,
124+ MultiValueMap <String , String > responseHeaders ) {
125+ this .rawResponseInputStream = rawResponseInputStream ;
126+ this .responseHeaders = responseHeaders ;
127+ }
128+
129+ @ Override
130+ protected int getResponseCode () {
131+ return HttpTransportConstants .STATUS_OK ;
132+ }
133+
134+ @ Override
135+ protected String getResponseMessage () {
136+ return "" ;
137+ }
138+
139+ @ Override
140+ protected long getResponseContentLength () {
141+ return Long .parseLong (
142+ this .responseHeaders .getOrDefault (HttpTransportConstants .HEADER_CONTENT_LENGTH , List .of ("-1" ))
143+ .get (0 ));
144+ }
145+
146+ @ Override
147+ protected InputStream getRawResponseInputStream () {
148+ return this .rawResponseInputStream ;
149+ }
150+
151+ @ Override
152+ protected OutputStream getRequestOutputStream () {
153+ throw new UnsupportedOperationException ();
154+ }
155+
156+ @ Override
157+ public Iterator <String > getResponseHeaderNames () {
158+ return this .responseHeaders .keySet ().iterator ();
159+ }
160+
161+ @ Override
162+ public Iterator <String > getResponseHeaders (String name ) {
163+ return this .responseHeaders .getOrDefault (name , Collections .emptyList ()).iterator ();
164+ }
165+
166+ @ Override
167+ public void addRequestHeader (String name , String value ) {
168+
169+ }
170+
171+ @ Override
172+ public URI getUri () throws URISyntaxException {
173+ return null ;
174+ }
175+
82176 }
83177
84178}
0 commit comments