1515 */
1616package feign .http2client .test ;
1717
18+ import static feign .Util .UTF_8 ;
1819import static org .assertj .core .api .Assertions .assertThat ;
20+ import static org .assertj .core .api .Assertions .entry ;
1921import static org .junit .jupiter .api .Assertions .assertThrows ;
2022
21- import feign .Body ;
22- import feign .Feign ;
23- import feign .FeignException ;
24- import feign .Headers ;
25- import feign .Request ;
26- import feign .RequestLine ;
27- import feign .Response ;
28- import feign .Retryer ;
23+ import feign .*;
24+ import feign .assertj .MockWebServerAssertions ;
2925import feign .client .AbstractClientTest ;
3026import feign .http2client .Http2Client ;
27+ import java .io .ByteArrayInputStream ;
3128import java .io .IOException ;
3229import java .net .http .HttpTimeoutException ;
30+ import java .util .Arrays ;
31+ import java .util .Collections ;
32+ import java .util .List ;
3333import java .util .concurrent .TimeUnit ;
3434import okhttp3 .mockwebserver .MockResponse ;
35- import org . junit . jupiter . api . Disabled ;
35+ import okhttp3 . mockwebserver . RecordedRequest ;
3636import org .junit .jupiter .api .Test ;
3737
3838/** Tests client-specific behavior, such as ensuring Content-Length is sent when specified. */
39- @ Disabled
4039public class Http2ClientTest extends AbstractClientTest {
4140
4241 public interface TestInterface {
@@ -59,6 +58,24 @@ public interface TestInterface {
5958 @ RequestLine ("DELETE /anything" )
6059 @ Body ("some request body" )
6160 String deleteWithBody ();
61+
62+ @ RequestLine ("POST /?foo=bar&foo=baz&qux=" )
63+ @ Headers ({"Foo: Bar" , "Foo: Baz" , "Qux: " , "Content-Type: text/plain" })
64+ Response post (String body );
65+
66+ @ RequestLine ("GET /" )
67+ @ Headers ("Accept: text/plain" )
68+ String get ();
69+
70+ @ RequestLine ("GET /?foo={multiFoo}" )
71+ Response get (@ Param ("multiFoo" ) List <String > multiFoo );
72+
73+ @ Headers ({"Authorization: {authorization}" })
74+ @ RequestLine ("GET /" )
75+ Response getWithHeaders (@ Param ("authorization" ) String authorization );
76+
77+ @ RequestLine (value = "GET /?foo={multiFoo}" , collectionFormat = CollectionFormat .CSV )
78+ Response getCSV (@ Param ("multiFoo" ) List <String > multiFoo );
6279 }
6380
6481 @ Override
@@ -117,12 +134,13 @@ public void veryLongResponseNullLength() {
117134
118135 @ Test
119136 void timeoutTest () {
120- server .enqueue (new MockResponse ().setBody ("foo" ).setBodyDelay ( 30 , TimeUnit .SECONDS ));
137+ server .enqueue (new MockResponse ().setBody ("foo" ).setHeadersDelay ( 1 , TimeUnit .SECONDS ));
121138
122139 final TestInterface api =
123140 newBuilder ()
124141 .retryer (Retryer .NEVER_RETRY )
125- .options (new Request .Options (1 , TimeUnit .SECONDS , 1 , TimeUnit .SECONDS , true ))
142+ .options (
143+ new Request .Options (500 , TimeUnit .MILLISECONDS , 500 , TimeUnit .MILLISECONDS , true ))
126144 .target (TestInterface .class , server .url ("/" ).toString ());
127145
128146 FeignException exception = assertThrows (FeignException .class , () -> api .timeout ());
@@ -145,6 +163,148 @@ void deleteWithRequestBody() {
145163 assertThat (result ).contains ("\" data\" : \" some request body\" " );
146164 }
147165
166+ @ Override
167+ @ Test
168+ public void parsesResponseMissingLength () throws IOException {
169+ server .enqueue (new MockResponse ().setChunkedBody ("foo" , 1 ));
170+
171+ TestInterface api =
172+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
173+
174+ Response response = api .post ("testing" );
175+ assertThat (response .status ()).isEqualTo (200 );
176+ // assertThat(response.reason()).isEqualTo("OK");
177+ assertThat (response .body ().length ()).isNull ();
178+ assertThat (response .body ().asInputStream ())
179+ .hasSameContentAs (new ByteArrayInputStream ("foo" .getBytes (UTF_8 )));
180+ }
181+
182+ @ Override
183+ @ Test
184+ public void parsesErrorResponse () {
185+
186+ server .enqueue (new MockResponse ().setResponseCode (500 ).setBody ("ARGHH" ));
187+
188+ TestInterface api =
189+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
190+
191+ Throwable exception = assertThrows (FeignException .class , () -> api .get ());
192+ assertThat (exception .getMessage ())
193+ .contains (
194+ "[500] during [GET] to [http://localhost:"
195+ + server .getPort ()
196+ + "/] [TestInterface#get()]: [ARGHH]" );
197+ }
198+
199+ @ Override
200+ @ Test
201+ public void defaultCollectionFormat () throws Exception {
202+ server .enqueue (new MockResponse ().setBody ("body" ));
203+
204+ TestInterface api =
205+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
206+
207+ Response response = api .get (Arrays .asList ("bar" , "baz" ));
208+
209+ assertThat (response .status ()).isEqualTo (200 );
210+ // assertThat(response.reason()).isEqualTo("OK");
211+
212+ MockWebServerAssertions .assertThat (server .takeRequest ())
213+ .hasMethod ("GET" )
214+ .hasPath ("/?foo=bar&foo=baz" );
215+ }
216+
217+ @ Override
218+ @ Test
219+ public void headersWithNotEmptyParams () throws InterruptedException {
220+ server .enqueue (new MockResponse ().setBody ("body" ));
221+
222+ TestInterface api =
223+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
224+
225+ Response response = api .getWithHeaders ("token" );
226+
227+ assertThat (response .status ()).isEqualTo (200 );
228+ // assertThat(response.reason()).isEqualTo("OK");
229+
230+ MockWebServerAssertions .assertThat (server .takeRequest ())
231+ .hasMethod ("GET" )
232+ .hasPath ("/" )
233+ .hasHeaders (entry ("authorization" , Collections .singletonList ("token" )));
234+ }
235+
236+ @ Override
237+ @ Test
238+ public void headersWithNullParams () throws InterruptedException {
239+ server .enqueue (new MockResponse ().setBody ("body" ));
240+
241+ TestInterface api =
242+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
243+
244+ Response response = api .getWithHeaders (null );
245+
246+ assertThat (response .status ()).isEqualTo (200 );
247+ // assertThat(response.reason()).isEqualTo("OK");
248+
249+ MockWebServerAssertions .assertThat (server .takeRequest ())
250+ .hasMethod ("GET" )
251+ .hasPath ("/" )
252+ .hasNoHeaderNamed ("Authorization" );
253+ }
254+
255+ @ Test
256+ public void alternativeCollectionFormat () throws Exception {
257+ server .enqueue (new MockResponse ().setBody ("body" ));
258+
259+ TestInterface api =
260+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
261+
262+ Response response = api .getCSV (Arrays .asList ("bar" , "baz" ));
263+
264+ assertThat (response .status ()).isEqualTo (200 );
265+ // assertThat(response.reason()).isEqualTo("OK");
266+
267+ // Some HTTP libraries percent-encode commas in query parameters and others
268+ // don't.
269+ MockWebServerAssertions .assertThat (server .takeRequest ())
270+ .hasMethod ("GET" )
271+ .hasOneOfPath ("/?foo=bar,baz" , "/?foo=bar%2Cbaz" );
272+ }
273+
274+ @ Override
275+ @ Test
276+ public void parsesRequestAndResponse () throws IOException , InterruptedException {
277+ server .enqueue (new MockResponse ().setBody ("foo" ).addHeader ("Foo: Bar" ));
278+
279+ TestInterface api =
280+ newBuilder ().target (TestInterface .class , "http://localhost:" + server .getPort ());
281+
282+ Response response = api .post ("foo" );
283+
284+ assertThat (response .status ()).isEqualTo (200 );
285+ // assertThat(response.reason()).isEqualTo("OK");
286+ assertThat (response .headers ())
287+ .hasEntrySatisfying (
288+ "Content-Length" ,
289+ value -> {
290+ assertThat (value ).contains ("3" );
291+ })
292+ .hasEntrySatisfying (
293+ "Foo" ,
294+ value -> {
295+ assertThat (value ).contains ("Bar" );
296+ });
297+ assertThat (response .body ().asInputStream ())
298+ .hasSameContentAs (new ByteArrayInputStream ("foo" .getBytes (UTF_8 )));
299+
300+ RecordedRequest recordedRequest = server .takeRequest ();
301+ assertThat (recordedRequest .getMethod ()).isEqualToIgnoringCase ("POST" );
302+ assertThat (recordedRequest .getHeader ("Foo" )).isEqualToIgnoringCase ("Bar, Baz" );
303+ assertThat (recordedRequest .getHeader ("Accept" )).isEqualToIgnoringCase ("*/*" );
304+ assertThat (recordedRequest .getHeader ("Content-Length" )).isEqualToIgnoringCase ("3" );
305+ assertThat (recordedRequest .getBody ().readUtf8 ()).isEqualToIgnoringCase ("foo" );
306+ }
307+
148308 @ Override
149309 public Feign .Builder newBuilder () {
150310 return Feign .builder ().client (new Http2Client ());
0 commit comments