1919import java .net .URISyntaxException ;
2020import java .net .http .HttpClient ;
2121import java .net .http .HttpClient .Redirect ;
22+ import java .net .http .HttpClient .Version ;
2223import java .net .http .HttpRequest ;
2324import java .net .http .HttpRequest .BodyPublisher ;
2425import java .net .http .HttpRequest .BodyPublishers ;
26+ import java .net .http .HttpRequest .Builder ;
2527import java .net .http .HttpResponse ;
2628import java .net .http .HttpResponse .BodyHandlers ;
2729import java .util .*;
2830import java .util .function .Function ;
2931import java .util .stream .Collectors ;
30- import feign .Client ;
31- import feign .Request ;
32+ import feign .*;
3233import feign .Request .Options ;
33- import feign .Response ;
3434
3535public class Http2Client implements Client {
3636
37+ private final HttpClient client ;
38+
39+ public Http2Client () {
40+ this (HttpClient .newBuilder ()
41+ .followRedirects (Redirect .ALWAYS )
42+ .version (Version .HTTP_2 )
43+ .build ());
44+ }
45+
46+ public Http2Client (HttpClient client ) {
47+ this .client = Util .checkNotNull (client , "http cliet must be not unll" );
48+ }
49+
3750 @ Override
3851 public Response execute (Request request , Options options ) throws IOException {
39- final HttpClient client = HttpClient .newBuilder ()
40- .followRedirects (Redirect .ALWAYS )
52+ final HttpRequest httpRequest = newRequestBuilder (request ).build ();
53+
54+ HttpResponse <byte []> httpResponse ;
55+ try {
56+ httpResponse = client .send (httpRequest , BodyHandlers .ofByteArray ());
57+ } catch (final InterruptedException e ) {
58+ throw new IOException ("Invalid uri " + request .url (), e );
59+ }
60+
61+ final OptionalLong length = httpResponse .headers ().firstValueAsLong ("Content-Length" );
62+
63+ final Response response = Response .builder ()
64+ .body (new ByteArrayInputStream (httpResponse .body ()),
65+ length .isPresent () ? (int ) length .getAsLong () : null )
66+ .reason (httpResponse .headers ().firstValue ("Reason-Phrase" ).orElse ("OK" ))
67+ .request (request )
68+ .status (httpResponse .statusCode ())
69+ .headers (castMapCollectType (httpResponse .headers ().map ()))
4170 .build ();
71+ return response ;
72+ }
4273
74+ private Builder newRequestBuilder (Request request ) throws IOException {
4375 URI uri ;
4476 try {
4577 uri = new URI (request .url ());
@@ -54,32 +86,29 @@ public Response execute(Request request, Options options) throws IOException {
5486 body = BodyPublishers .ofByteArray (request .body ());
5587 }
5688
57- final HttpRequest httpRequest = HttpRequest .newBuilder ()
89+ final Builder requestBuilder = HttpRequest .newBuilder ()
5890 .uri (uri )
59- .method (request .method (), body )
60- .headers (asString (filterRestrictedHeaders (request .headers ())))
61- .build ();
91+ .version (Version .HTTP_2 );
6292
63- HttpResponse <byte []> httpResponse ;
64- try {
65- httpResponse = client .send (httpRequest , BodyHandlers .ofByteArray ());
66- } catch (final InterruptedException e ) {
67- throw new IOException ("Invalid uri " + request .url (), e );
93+ final Map <String , Collection <String >> headers = filterRestrictedHeaders (request .headers ());
94+ if (!headers .isEmpty ()) {
95+ requestBuilder .headers (asString (headers ));
6896 }
6997
70- System .out .println (httpResponse .headers ().map ());
71-
72- final OptionalLong length = httpResponse .headers ().firstValueAsLong ("Content-Length" );
98+ switch (request .httpMethod ()) {
99+ case GET :
100+ return requestBuilder .GET ();
101+ case POST :
102+ return requestBuilder .POST (body );
103+ case PUT :
104+ return requestBuilder .PUT (body );
105+ case DELETE :
106+ return requestBuilder .DELETE ();
107+ default :
108+ // fall back scenario, http implementations may restrict some methods
109+ return requestBuilder .method (request .httpMethod ().toString (), body );
110+ }
73111
74- final Response response = Response .builder ()
75- .body (new ByteArrayInputStream (httpResponse .body ()),
76- length .isPresent () ? (int ) length .getAsLong () : null )
77- .reason (httpResponse .headers ().firstValue ("Reason-Phrase" ).orElse (null ))
78- .request (request )
79- .status (httpResponse .statusCode ())
80- .headers (castMapCollectType (httpResponse .headers ().map ()))
81- .build ();
82- return response ;
83112 }
84113
85114 /**
@@ -98,12 +127,16 @@ public Response execute(Request request, Options options) throws IOException {
98127 }
99128
100129 private Map <String , Collection <String >> filterRestrictedHeaders (Map <String , Collection <String >> headers ) {
101- return headers .keySet ()
130+ final Map < String , Collection < String >> filteredHeaders = headers .keySet ()
102131 .stream ()
103132 .filter (headerName -> !DISALLOWED_HEADERS_SET .contains (headerName ))
104133 .collect (Collectors .toMap (
105134 Function .identity (),
106135 headers ::get ));
136+
137+ filteredHeaders .computeIfAbsent ("Accept" , key -> List .of ("*/*" ));
138+
139+ return filteredHeaders ;
107140 }
108141
109142 private Map <String , Collection <String >> castMapCollectType (Map <String , List <String >> map ) {
0 commit comments