Chapters
java.net.http package provides high-level client interfaces to HTTP (versions 1.1 and 2) and low-level client interfaces to WebSocket. This package has classes that can be alternatives to URLConnection, HttpURLConnection and HttpsURLConnection.
I discussed HttpURLConnection and HttpsURLConnection in this article. One of the advantages of this package over URLConnection is that this package can asynchronously handle HTTP requests and responses.
HttpRequest is used to create a request that is sent to a server. HttpClient is used to send request to a server and get server's response to the request. HttpResponse holds response that has been sent by server to a client.
First off, we need to create a HttpRequest and HttpClient. HttpResponse can't be created directly. It's created once HttpClient retrieves server's response. To create a HttpRequest and HttpClient, we need to created builders by invoking
If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_get.php". Then, put these codes in the php file:
In the example above, I used the third form of
a GET query with multiple values looks like this:
Request method is optional.
Next, to create a HttpClient, we invoke
Next, once we have created a HttpRequest and HttpClient, we can invoke
The class HttpResponse.BodyHandlers provides implementations of many common body handlers.
Next, once
Next, let's change the request method to POST. If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_post.php". Then, put these codes in the php file:
Handling redirects here is similar to handling redirects in HttpURLConnection. You may wanna look at this article regarding handling redirects in HttpURLConnection.
This example demonstrates handling redirects manually.
If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_get.php". Then, put these codes in the php file:
Java provides HttpRequest.BodyPublishers and HttpResponse.BodySubscribers that contain useful implementations of BodyPublisher and BodySubscriber. Although, you can create your own implementations if the implementations that java provide don't suffice.
Push Promise is a new feature in HTTP/2(HTTP version 2) that allows server to push resources to the browser without making clients request for them. Push promise increases performance such as page loading. Java supports handling Push Promises via
This example demonstrates handling push promise.
of method is a static method that returns a push promise handler that accumulates push promises, and their responses, into the given map.
Overview
java.net.http package provides high-level client interfaces to HTTP (versions 1.1 and 2) and low-level client interfaces to WebSocket. This package has classes that can be alternatives to URLConnection, HttpURLConnection and HttpsURLConnection.
I discussed HttpURLConnection and HttpsURLConnection in this article. One of the advantages of this package over URLConnection is that this package can asynchronously handle HTTP requests and responses.
HttpRequest, HttpClient and HttpResponse
HttpRequest is used to create a request that is sent to a server. HttpClient is used to send request to a server and get server's response to the request. HttpResponse holds response that has been sent by server to a client.
First off, we need to create a HttpRequest and HttpClient. HttpResponse can't be created directly. It's created once HttpClient retrieves server's response. To create a HttpRequest and HttpClient, we need to created builders by invoking
newBuilder()
method. Once we're done building them, we invoke their build()
methods.
If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_get.php". Then, put these codes in the php file:
<?php echo str_shuffle($_GET['text']); ?>This example demonstrates HttpRequest, HttpClient and HttpResponse.
import java.net.http.*; import java.net.*; import java.io.IOException; public class SampleClass{ public static void main(String[] args) throws Exception{ //Request HttpRequest request = HttpRequest. newBuilder(new URI("http://localhost/"+ "test/url_con_test_get.php?text=myText")). version(HttpClient.Version.HTTP_2). headers("Content-Type", "text/plain;charset=UTF-8"). GET(). build(); //Request-response handler HttpClient handler = HttpClient. newBuilder().build(); HttpResponse<String> response = handler.send (request, HttpResponse.BodyHandlers.ofString()); System.out.println("response: " + response.body()); } } Result(may vary) response: temyxTFirst off, to create a HttpRequest, we invoke
HttpRequest.newBuilder
method. This method returns HttpRequest.Builder instance. newBuilder
has three forms:
newBuilder() - Creates an HttpRequest builder.
newBuilder(HttpRequest request, BiPredicate<String,String> filter) - Creates a Builder whose initial state is copied from an existing HttpRequest.
newBuilder(URI uri) - Creates an HttpRequest builder with the given URI.
In the example above, I used the third form of
newBuilder
method. version
method in HttpRequest.Builder sets the preferred HttpClient.Version for this request. This method returns HttpRequest.Builder with the specified HttpClient.Version. Take note that if the specified version is HttpClient.Version.HTTP_2
and HTTP version 2
is not supported, the specified version will rollback to HTTP version 1.1
. Adding version in HttpRequest is optional.
headers
method in HttpRequest.Builder adds the given key-value pairs to the set of headers for the request. HTTP header consists of a key-value pair. key
denotes header name and value
denotes the value of the header.
headers
method has another variant which is the header
method. header
method only accepts a single key-value pair. Although, it can be invoked multiple times. Adding headers in HttpRequest is optional.
GET
method Sets the request method of builder to GET. build()
builds an HttpRequest with the specified version, headers, request method, etc. Just a reminder, a GET query with a single value looks like this: ?name=value
a GET query with multiple values looks like this:
?name1=value1&name2=value2
Request method is optional.
Next, to create a HttpClient, we invoke
HttpClient.newBuilder
method. This method returns HttpClient.Builder instance. If we just want to create a HttpClient with default settings, we can invoke HttpClient.newHttpClient
method. This syntax HttpClient.newBuilder().build()
is equivalent to invoking HttpClient.newHttpClient
.
Next, once we have created a HttpRequest and HttpClient, we can invoke
send
method. This method requires HttpRequest and HttpResponse.BodyHandler arguments. HttpResponse.BodyHandler<T> is a handler for response bodies.
The class HttpResponse.BodyHandlers provides implementations of many common body handlers.
HttpResponse.BodyHandlers.ofString()
method indicatees that the response body is going to be String type.
send
method has another variant which is the sendAsync
method. sendAsync
method is used for asynchronous request-response tasks. send
method is used for synchronous request-response task.
Next, once
send
method returns a HttpResponse, we can get the response body by invoking the body()
method of HttpResponse.
Next, let's change the request method to POST. If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_post.php". Then, put these codes in the php file:
<?php echo str_shuffle($_POST['text']); ?>This example demonstrates POST request method.
import java.net.http.*; import java.net.*; import java.io.IOException; import java.time.Duration; public class SampleClass{ public static void main(String[] args) throws Exception{ //Request HttpRequest request = HttpRequest. newBuilder(new URI("http://localhost/"+ "test/url_con_test_post.php")). timeout(Duration.ofSeconds(5)). version(HttpClient.Version.HTTP_2). headers("Content-Type", "application/x-www-form-urlencoded"). //or "text1=String1&text2=String2" //for multiple key-value pairs POST(HttpRequest.BodyPublishers. ofString("text=String")). build(); //Request-response handler HttpClient handler = HttpClient. newBuilder().build(); HttpResponse<String> response = handler.send (request, HttpResponse.BodyHandlers.ofString()); System.out.println("response: " + response.body()); } } Result(may vary) ngSrti
application/x-www-form-urlencoded
is used to handle POST data. There's another Content-Type value that handles POST data and that's the multipart/form-data
. I think this discussion has a good explanation regarding the difference of these two Content-Type values.
timeout
method sets a timeout for this request. If the response is not received within the specified timeout then an HttpTimeoutException
is thrown from HttpClient::send
or HttpClient::sendAsync
completes exceptionally with an HttpTimeoutException
. Setting timeout is optional.
HttpRequest.BodyPublishers
contains implementations of BodyPublisher that implement various useful publishers, such as publishing the request body from a String, or from a file. Request body is not limited to String, we can create a request body for bytes, input stream or even a file. You can read the examples about request body types in the documentation.
Handling Redirects
Handling redirects here is similar to handling redirects in HttpURLConnection. You may wanna look at this article regarding handling redirects in HttpURLConnection.
This example demonstrates handling redirects manually.
import java.net.http.*; import java.net.*; import java.io.IOException; import java.time.Duration; import java.util.Optional; public class SampleClass{ public static void main(String[] args) throws Exception{ URI uri = URI.create("http://www.twitter.com"); boolean checkRedirect = true; HttpRequest request = null; HttpClient handler = null; HttpResponse<Void> response = null; while(checkRedirect){ //Request request = HttpRequest. newBuilder(uri). timeout(Duration.ofSeconds(5)). build(); //HttpClient handler = HttpClient. newBuilder(). followRedirects(HttpClient.Redirect.NEVER). build(); response = handler.send(request, HttpResponse.BodyHandlers.discarding()); if(response.statusCode() == HttpURLConnection.HTTP_MOVED_PERM || response.statusCode() == HttpURLConnection.HTTP_MOVED_TEMP || response.statusCode() == HttpURLConnection.HTTP_SEE_OTHER){ Optional<String> redirect = response.headers().firstValue("Location"); System.out.println ("Redirect URL: " + redirect.get()); uri = URI.create(redirect.get()); }else checkRedirect = false; } } } Result Redirect URL: https://www.twitter.com Redirect URL: https://twitter.com
followRedirects
in HttpClient.Builder specifies whether requests will automatically follow redirects issued by the server. HttpClient has three policies regarding following redirects and they can be found in HttpClient.Redirect enum.
HttpClient.Redirect.NEVER
means that HttpClient will never automatically follow redirects. If you wanna automatically follow redirects you can use HttpClient.Redirect.ALWAYS
. Careful thougn, Following redirects can be dangerous.
HttpResponse.BodyHandlers.discarding
method returns a response body handler that discards the response body. Since we don't need response body in the example above, it's alright to discard it. headers
method in HttpResponse returns the response headers. This method return a HttpHeaders instance.
firstValue
method returns the first value of a header. Some HTTP headers can have multiple values. Location
header only has one value which is the redirect URL.
Sending HTTP Requests Asynchronously
If you wanna try the example below, you need a web server like apache web server. You can install XAMPP to easily install apache web server. Once you have apache web server, start the server, create a directory and name it as "test" in your document root and create a php file there. Name the php file as "url_con_test_get.php". Then, put these codes in the php file:
<?php echo str_shuffle($_GET['text']); ?>To send requests asynchronously, we will use the
sendAsync
method from HttpClient. This example demonstrates sendAsync
method.
import java.net.http.*; import java.net.*; import java.io.IOException; import java.time.Duration; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.ArrayList; public class SampleClass{ public static void main(String[] args) throws InterruptedException, ExecutionException{ int ln = 2; URI[] uris = new URI[ln]; uris[0] = URI.create("http://localhost/"+ "test/url_con_test_get.php?text=String1"); uris[1] = URI.create("http://localhost/"+ "test/url_con_test_get.php?text=String2"); HttpRequest[] requests = new HttpRequest[ln]; //Request-response handler HttpClient handler = HttpClient. newHttpClient(); ArrayList <CompletableFuture<HttpResponse <String>>> responses = new ArrayList<>(); //requests for(int i = 0; i < ln; i++){ requests[i] = HttpRequest.newBuilder(uris[i]). headers("Content-Type", "text/plain;charset=UTF-8"). GET().build(); } //responses for(int i = 0; i < ln; i++){ responses.add (handler.sendAsync(requests[i], HttpResponse.BodyHandlers.ofString())); } for( CompletableFuture <HttpResponse<String>> r : responses) System.out.println(r.get().body()); } } Result(may vary) irn1tSg rSgin2tIf you're not familiar with CompletableFuture class, I explained the class in this article. If you wanna implement your own executor, invoke
executor
method of HttpClient.Builder
. For example:
ExecutorService myExecutor... ... HttpClient handler = HttpClient. newBuilder(). executor(myExecutor). build();The default executor that HttpClient uses is
java.util.concurrent.Executors.newCachedThreadPool()
. Also, Take note that Flow API has been implemented to HttpRequest, HttpClient and HttpResponse. HttpRequest has BodyPublisher whereas HttpResponse has BodySubsriber. HttpClient is acting like Flow.processor. I explained Flow API in article.
Java provides HttpRequest.BodyPublishers and HttpResponse.BodySubscribers that contain useful implementations of BodyPublisher and BodySubscriber. Although, you can create your own implementations if the implementations that java provide don't suffice.
HTTP/2 Push Promise
Push Promise is a new feature in HTTP/2(HTTP version 2) that allows server to push resources to the browser without making clients request for them. Push promise increases performance such as page loading. Java supports handling Push Promises via
sendAsync
method. I think this article has a good explanation regarding push promise. You should read it.
This example demonstrates handling push promise.
import java.net.http.*; import java.net.*; import java.time.Duration; import java.util.function.Function; import java.util.concurrent.CompletableFuture; public class SampleClass{ public static void main(String[] args) throws Exception{ URI uri = URI.create("https://http2.golang.org/serverpush"); HttpRequest pageRequest = HttpRequest.newBuilder(uri). timeout(Duration.ofSeconds(5)). build(); HttpClient handler = HttpClient.newBuilder(). version(HttpClient.Version.HTTP_2). build(); HttpResponse.PushPromiseHandler<String> pp = (HttpRequest initiatingRequest, HttpRequest pushPromiseRequest, Function<HttpResponse.BodyHandler<String>, CompletableFuture<HttpResponse<String>>> acceptor) -> { acceptor.apply(HttpResponse.BodyHandlers.ofString()). thenAccept(respo -> { System.out.println("Pushed Response: " + respo.uri()); System.out.println("Headers: " + respo.headers()); System.out.println(); }); System.out.println ("Promise Request: " + pushPromiseRequest.uri()); System.out.println ("Request Headers: " + pushPromiseRequest.headers()); }; CompletableFuture<HttpResponse<String>> response = handler.sendAsync(pageRequest, HttpResponse.BodyHandlers.ofString(),pp); System.out.println ("Response Status Code: " + response.get().statusCode()); System.out.println("Requested Page"); System.out.println(response.get().body()); } }HttpResponse.PushPromiseHandler has two methods. applyPushPromise method is an abstract method where push promise resources is being received. This is the method that is defined in
pp
variable.
of method is a static method that returns a push promise handler that accumulates push promises, and their responses, into the given map.
No comments:
Post a Comment