11package com .recurly .v3 .http ;
22
3+ import java .io .ByteArrayOutputStream ;
34import java .io .IOException ;
5+ import java .io .InputStream ;
6+ import java .io .OutputStream ;
7+ import java .net .HttpURLConnection ;
8+ import java .net .URL ;
9+ import java .nio .charset .StandardCharsets ;
410import java .util .HashMap ;
11+ import java .util .List ;
512import java .util .Map ;
6- import java .util .concurrent .TimeUnit ;
7- import okhttp3 .Headers ;
8- import okhttp3 .MediaType ;
9- import okhttp3 .OkHttpClient ;
10- import okhttp3 .Request ;
11- import okhttp3 .RequestBody ;
12- import okhttp3 .Response ;
13- import okhttp3 .ResponseBody ;
14- import okhttp3 .logging .HttpLoggingInterceptor ;
13+ import java .util .zip .GZIPInputStream ;
1514
1615public class DefaultHttpAdapter implements HttpAdapter {
1716 private static final int DEFAULT_TIMEOUT_MS = 60_000 ;
1817
19- private final OkHttpClient httpClient ;
18+ private final int timeoutMs ;
2019
2120 public DefaultHttpAdapter () {
2221 this (DEFAULT_TIMEOUT_MS );
2322 }
2423
2524 public DefaultHttpAdapter (final int timeoutMs ) {
26- final OkHttpClient .Builder builder =
27- new OkHttpClient .Builder ()
28- .connectTimeout (timeoutMs , TimeUnit .MILLISECONDS )
29- .readTimeout (timeoutMs , TimeUnit .MILLISECONDS )
30- .writeTimeout (timeoutMs , TimeUnit .MILLISECONDS );
31-
32- if (envEnabled ("RECURLY_INSECURE" ) && envEnabled ("RECURLY_DEBUG" )) {
33- final HttpLoggingInterceptor logging = new HttpLoggingInterceptor ();
34- logging .setLevel (HttpLoggingInterceptor .Level .BASIC );
35- builder .addInterceptor (logging );
36- }
37-
38- this .httpClient = builder .build ();
25+ this .timeoutMs = timeoutMs ;
3926 }
4027
4128 @ Override
@@ -45,51 +32,87 @@ public HttpResponse execute(
4532 final Map <String , String > headers ,
4633 final String body )
4734 throws IOException {
48- final Request .Builder requestBuilder = new Request .Builder ().url (url );
35+ final boolean debug = envEnabled ("RECURLY_INSECURE" ) && envEnabled ("RECURLY_DEBUG" );
36+ if (debug ) {
37+ System .out .println ("--> " + method + " " + url );
38+ }
39+ final long startMs = System .currentTimeMillis ();
4940
41+ final HttpURLConnection connection = (HttpURLConnection ) new URL (url ).openConnection ();
42+ connection .setRequestMethod (method );
43+ connection .setConnectTimeout (timeoutMs );
44+ connection .setReadTimeout (timeoutMs );
45+
46+ boolean callerSetAcceptEncoding = false ;
5047 for (final Map .Entry <String , String > header : headers .entrySet ()) {
51- requestBuilder .header (header .getKey (), header .getValue ());
48+ connection .setRequestProperty (header .getKey (), header .getValue ());
49+ if ("Accept-Encoding" .equalsIgnoreCase (header .getKey ())) {
50+ callerSetAcceptEncoding = true ;
51+ }
52+ }
53+ if (!callerSetAcceptEncoding ) {
54+ connection .setRequestProperty ("Accept-Encoding" , "gzip" );
5255 }
5356
54- final RequestBody requestBody =
55- body != null
56- ? RequestBody .create (body , MediaType .parse ("application/json; charset=utf-8" ))
57- : RequestBody .create (new byte [0 ]);
58-
59- switch (method ) {
60- case "HEAD" :
61- requestBuilder .head ();
62- break ;
63- case "GET" :
64- requestBuilder .get ();
65- break ;
66- case "POST" :
67- requestBuilder .post (requestBody );
68- break ;
69- case "PUT" :
70- requestBuilder .put (requestBody );
71- break ;
72- case "DELETE" :
73- requestBuilder .delete ();
74- break ;
75- default :
76- throw new IllegalArgumentException (method + " is not a valid Recurly HTTP method" );
57+ if (body != null || "POST" .equals (method ) || "PUT" .equals (method )) {
58+ connection .setDoOutput (true );
59+ final byte [] bodyBytes = body != null ? body .getBytes (StandardCharsets .UTF_8 ) : new byte [0 ];
60+ try (final OutputStream out = connection .getOutputStream ()) {
61+ out .write (bodyBytes );
62+ }
7763 }
7864
79- try (final Response response = httpClient .newCall (requestBuilder .build ()).execute ()) {
80- final int statusCode = response .code ();
65+ final int statusCode = connection .getResponseCode ();
8166
82- final Map <String , String > responseHeaders = new HashMap <>();
83- final Headers okHeaders = response .headers ();
84- for (int i = 0 ; i < okHeaders .size (); i ++) {
85- responseHeaders .put (okHeaders .name (i ).toLowerCase (), okHeaders .value (i ));
67+ final Map <String , String > responseHeaders = new HashMap <>();
68+ for (final Map .Entry <String , List <String >> entry : connection .getHeaderFields ().entrySet ()) {
69+ final String key = entry .getKey ();
70+ if (key != null && !entry .getValue ().isEmpty ()) {
71+ responseHeaders .put (key .toLowerCase (), entry .getValue ().get (0 ));
8672 }
73+ }
74+
75+ final InputStream inputStream ;
76+ if ("HEAD" .equals (method )) {
77+ inputStream = null ;
78+ } else {
79+ inputStream = statusCode >= 400 ? connection .getErrorStream () : connection .getInputStream ();
80+ }
8781
88- final ResponseBody responseBody = response .body ();
89- final byte [] responseBodyBytes = responseBody != null ? responseBody .bytes () : new byte [0 ];
82+ final String contentEncoding = responseHeaders .get ("content-encoding" );
83+ final boolean gzipEncoded = contentEncoding != null && "gzip" .equalsIgnoreCase (contentEncoding .trim ());
84+
85+ final byte [] responseBodyBytes ;
86+ if (inputStream == null ) {
87+ responseBodyBytes = new byte [0 ];
88+ } else {
89+ try (final InputStream rawStream = inputStream ;
90+ final InputStream is = gzipEncoded ? new GZIPInputStream (rawStream ) : rawStream ) {
91+ responseBodyBytes = readAllBytes (is );
92+ }
93+ }
94+
95+ if (gzipEncoded ) {
96+ responseHeaders .remove ("content-encoding" );
97+ responseHeaders .remove ("content-length" );
98+ }
99+
100+ if (debug ) {
101+ System .out .println (
102+ "<-- " + statusCode + " " + url + " (" + (System .currentTimeMillis () - startMs ) + "ms)" );
103+ }
104+
105+ return new HttpResponse (statusCode , responseHeaders , responseBodyBytes );
106+ }
90107
91- return new HttpResponse (statusCode , responseHeaders , responseBodyBytes );
108+ private static byte [] readAllBytes (final InputStream inputStream ) throws IOException {
109+ final ByteArrayOutputStream buffer = new ByteArrayOutputStream ();
110+ final byte [] chunk = new byte [8192 ];
111+ int n ;
112+ while ((n = inputStream .read (chunk )) != -1 ) {
113+ buffer .write (chunk , 0 , n );
92114 }
115+ return buffer .toByteArray ();
93116 }
94117
95118 private static boolean envEnabled (final String envVar ) {
0 commit comments