11package serpapi ;
22
3- import javax .net .ssl .*;
43import java .io .*;
5- import java .net .HttpURLConnection ;
6- import java .net .URL ;
7- import java .security . KeyManagementException ;
8- import java .security . NoSuchAlgorithmException ;
9- import java .security . cert . X509Certificate ;
4+ import java .net .URI ;
5+ import java .net .http . HttpClient ;
6+ import java .net . http . HttpRequest ;
7+ import java .net . http . HttpResponse ;
8+ import java .time . Duration ;
109import java .util .Map ;
1110
1211import com .google .gson .Gson ;
1312import com .google .gson .JsonObject ;
14- import com .google .gson .JsonPrimitive ;
1513
1614/**
1715 * HTTPS client for Serp API
1816 */
1917public class SerpApiHttp {
2018 // http request configuration
21- private int httpConnectionTimeout ;
22- private int httpReadTimeout ;
19+ private int httpConnectionTimeout = 60000 ;
20+ private int httpReadTimeout = 60000 ;
2321
2422 /**
2523 * current API version
@@ -41,84 +39,20 @@ public class SerpApiHttp {
4139 */
4240 public String path ;
4341
42+ /**
43+ * HTTP client
44+ */
45+ private HttpClient httpClient ;
46+
4447 /***
4548 * Constructor
4649 * @param path HTTP url path
4750 */
4851 public SerpApiHttp (String path ) {
4952 this .path = path ;
50- }
51-
52- /***
53- * Connect socket connection
54- *
55- * @param path url end point
56- * @param parameter client parameters like: { "q": "coffee", "location": "Austin, TX"}
57- * @return HttpURLConnection connection object
58- * @throws SerpApiException wraps error message
59- */
60- protected HttpURLConnection connect (String path , Map <String , String > parameter ) throws SerpApiException {
61- HttpURLConnection con ;
62- try {
63- allowHTTPS ();
64- String query = ParameterStringBuilder .getParamsString (parameter );
65- URL url = new URL (BACKEND + path + "?" + query );
66- con = (HttpURLConnection ) url .openConnection ();
67- con .setRequestMethod ("GET" );
68- } catch (IOException e ) {
69- throw new SerpApiException (e );
70- } catch (NoSuchAlgorithmException e ) {
71- e .printStackTrace ();
72- throw new SerpApiException (e );
73- } catch (KeyManagementException e ) {
74- e .printStackTrace ();
75- throw new SerpApiException (e );
76- }
77-
78- String outputFormat = parameter .get ("output" );
79- if (outputFormat == null ) {
80- throw new SerpApiException ("output format must be defined: " + path );
81- } else if (outputFormat .startsWith ("json" )) {
82- con .setRequestProperty ("Content-Type" , "application/json" );
83- }
84- con .setConnectTimeout (getHttpConnectionTimeout ());
85- con .setReadTimeout (getHttpReadTimeout ());
86-
87- con .setDoOutput (true );
88- return con ;
89- }
90-
91- // Allow HTTPS support with legacy java version
92- private void allowHTTPS () throws NoSuchAlgorithmException , KeyManagementException {
93- TrustManager [] trustAllCerts ;
94- trustAllCerts = new TrustManager [] { new X509TrustManager () {
95- public X509Certificate [] getAcceptedIssuers () {
96- return null ;
97- }
98-
99- public void checkClientTrusted (X509Certificate [] certs , String authType ) {
100- }
101-
102- public void checkServerTrusted (X509Certificate [] certs , String authType ) {
103- }
104-
105- } };
106-
107- SSLContext sc = SSLContext .getInstance ("SSL" );
108- sc .init (null , trustAllCerts , new java .security .SecureRandom ());
109- HttpsURLConnection .setDefaultSSLSocketFactory (sc .getSocketFactory ());
110-
111- // Create all-trusting host name verifier
112- HostnameVerifier allHostsValid = new HostnameVerifier () {
113- public boolean verify (String hostname , SSLSession session ) {
114- return true ;
115- }
116- };
117- // Install the all-trusting host verifier
118- HttpsURLConnection .setDefaultHostnameVerifier (allHostsValid );
119- /*
120- * end of the fix
121- */
53+ this .httpClient = HttpClient .newBuilder ()
54+ .connectTimeout (Duration .ofMillis (httpConnectionTimeout ))
55+ .build ();
12256 }
12357
12458 /***
@@ -129,47 +63,35 @@ public boolean verify(String hostname, SSLSession session) {
12963 * @throws SerpApiException wraps error message
13064 */
13165 public String get (Map <String , String > parameter ) throws SerpApiException {
132- HttpURLConnection con = connect (this .path , parameter );
133-
134- // Get HTTP status
135- int statusCode = -1 ;
136- // Hold response stream
137- InputStream is = null ;
138- // Read buffer
139- BufferedReader in = null ;
66+ String query ;
14067 try {
141- statusCode = con .getResponseCode ();
68+ query = ParameterStringBuilder .getParamsString (parameter );
69+ } catch (UnsupportedEncodingException e ) {
70+ throw new SerpApiException (e );
71+ }
14272
143- if (statusCode == 200 ) {
144- is = con .getInputStream ();
145- } else {
146- is = con .getErrorStream ();
147- }
73+ URI uri = URI .create (BACKEND + path + "?" + query );
14874
149- Reader reader = new InputStreamReader (is );
150- in = new BufferedReader (reader );
151- } catch (IOException e ) {
152- throw new SerpApiException (e );
75+ HttpRequest .Builder requestBuilder = HttpRequest .newBuilder ()
76+ .uri (uri )
77+ .timeout (Duration .ofMillis (httpReadTimeout ))
78+ .GET ();
79+
80+ String outputFormat = parameter .get ("output" );
81+ if (outputFormat != null && outputFormat .startsWith ("json" )) {
82+ requestBuilder .header ("Content-Type" , "application/json" );
15383 }
15484
155- String inputLine ;
156- StringBuffer content = new StringBuffer ();
15785 try {
158- while ((inputLine = in .readLine ()) != null ) {
159- content .append (inputLine );
86+ HttpResponse <String > response = httpClient .send (requestBuilder .build (), HttpResponse .BodyHandlers .ofString ());
87+
88+ if (response .statusCode () != 200 ) {
89+ triggerSerpApiException (response .body ());
16090 }
161- in . close ();
162- } catch (IOException e ) {
91+ return response . body ();
92+ } catch (IOException | InterruptedException e ) {
16393 throw new SerpApiException (e );
16494 }
165-
166- // Disconnect
167- con .disconnect ();
168-
169- if (statusCode != 200 ) {
170- triggerSerpApiException (content .toString ());
171- }
172- return content .toString ();
17395 }
17496
17597 /**
@@ -183,7 +105,7 @@ protected void triggerSerpApiException(String content) throws SerpApiException {
183105 JsonObject element = gson .fromJson (content , JsonObject .class );
184106 errorMessage = element .get ("error" ).getAsString ();
185107 } catch (Exception e ) {
186- throw new AssertionError ("invalid response format: " + content );
108+ throw new SerpApiException ("invalid response format: " + content );
187109 }
188110 throw new SerpApiException (errorMessage );
189111 }
@@ -204,6 +126,10 @@ public int getHttpConnectionTimeout() {
204126 */
205127 public void setHttpConnectionTimeout (int httpConnectionTimeout ) {
206128 this .httpConnectionTimeout = httpConnectionTimeout ;
129+ // Recreate client with new timeout
130+ this .httpClient = HttpClient .newBuilder ()
131+ .connectTimeout (Duration .ofMillis (httpConnectionTimeout ))
132+ .build ();
207133 }
208134
209135 /**
0 commit comments