Sending HTTP POST Request In Java
Asked Answered
F

13

365

Given this URL:

http://www.example.com/page.php?id=10            

I want to send the id = 10 to the server's page.php, which accepts it in a POST method.

How can I do this with Java?

I tried this :

URL aaa = new URL("http://www.example.com/page.php");
URLConnection ccc = aaa.openConnection();

But I still can't figure out how to send it with POST method.

Filberto answered 24/7, 2010 at 10:28 Comment(0)
P
385

Updated answer

Since some of the classes, in the original answer, are deprecated in the newer version of Apache HTTP Components, I'm posting this update.

By the way, you can access the full documentation for more examples here.

HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.a-domain.example/foo/");

// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("param-1", "12345"));
params.add(new BasicNameValuePair("param-2", "Hello!"));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();

if (entity != null) {
    try (InputStream instream = entity.getContent()) {
        // do something useful
    }
}

Original answer

I recommend to use Apache HttpClient. its faster and easier to implement.

HttpPost post = new HttpPost("http://jakarata.apache.org/");
NameValuePair[] data = {
    new NameValuePair("user", "joe"),
    new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.

for more information check this URL: http://hc.apache.org/

Princeling answered 24/7, 2010 at 12:25 Comment(12)
After trying for a while to get my hands on PostMethod it seems its actually now called HttpPost as per https://mcmap.net/q/58033/-http-multipart-classes-in-java - just for anyone finding this answer like I did :)Linnealinnean
@Juan (and Martin Lyne) thank you for the comments. I just updated the answer.Princeling
Does your revised answer still use hc.apache.org ?Fellini
@Fellini yes. there is a link to apache-hc in the revised answer too.Princeling
I get java.lang.NoSuchFieldError: INSTANCE at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:144) at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:966) at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)Compliancy
you should add the imported libsCattle
For this to work, you need httpcore and httpclient from hc.apache.org/downloads.cgi, download extract and add the two jar files into your projectDemonology
Its giving this error: The constructor UrlEncodedFormEntity(List<NameValuePair>, String) is undefinedAstrogate
And also giving an error that cannot resolve getEntity()Astrogate
For anyone getting the same issue as @AdarshSingh, I found a solution after looking at this provided example. Just change HttpClient to CloseableHttpClient, and HttpResponse to CloseableHttpResponse!Llewellyn
Note that the documentation link is now broken. Is this still the best way to make http requests?Varmint
Ok, but how to get the response of this post request ?Monitory
P
257

Sending a POST request is easy in vanilla Java. Starting with a URL, we need t convert it to a URLConnection using url.openConnection();. After that, we need to cast it to a HttpURLConnection, so we can access its setRequestMethod() method to set our method. We finally say that we are going to send data over the connection.

URL url = new URL("https://www.example.com/login");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod("POST"); // PUT is another valid option
http.setDoOutput(true);

We then need to state what we are going to send:

Sending a simple form

A normal POST coming from a http form has a well defined format. We need to convert our input to this format:

Map<String,String> arguments = new HashMap<>();
arguments.put("username", "root");
arguments.put("password", "sjh76HSn!"); // This is a fake password obviously
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
    sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" 
         + URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;

We can then attach our form contents to the http request with proper headers and send it.

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()

Sending JSON

We can also send json using java, this is also easy:

byte[] out = "{\"username\":\"root\",\"password\":\"password\"}" .getBytes(StandardCharsets.UTF_8);
int length = out.length;

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()

Remember that different servers accept different content-types for json, see this question.


Sending files with java post

Sending files can be considered more challenging to handle as the format is more complex. We are also going to add support for sending the files as a string, since we don't want to buffer the file fully into the memory.

For this, we define some helper methods:

private void sendFile(OutputStream out, String name, InputStream in, String fileName) {
    String o = "Content-Disposition: form-data; name=\"" + URLEncoder.encode(name,"UTF-8") 
             + "\"; filename=\"" + URLEncoder.encode(filename,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    byte[] buffer = new byte[2048];
    for (int n = 0; n >= 0; n = in.read(buffer))
        out.write(buffer, 0, n);
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}

private void sendField(OutputStream out, String name, String field) {
    String o = "Content-Disposition: form-data; name=\"" 
             + URLEncoder.encode(name,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    out.write(URLEncoder.encode(field,"UTF-8").getBytes(StandardCharsets.UTF_8));
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}

We can then use these methods to create a multipart post request as follows:

String boundary = UUID.randomUUID().toString();
byte[] boundaryBytes = 
           ("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8);
byte[] finishBoundaryBytes = 
           ("--" + boundary + "--").getBytes(StandardCharsets.UTF_8);
http.setRequestProperty("Content-Type", 
           "multipart/form-data; charset=UTF-8; boundary=" + boundary);

// Enable streaming mode with default settings
http.setChunkedStreamingMode(0); 

// Send our fields:
try(OutputStream out = http.getOutputStream()) {
    // Send our header (thx Algoman)
    out.write(boundaryBytes);

    // Send our first field
    sendField(out, "username", "root");

    // Send a seperator
    out.write(boundaryBytes);

    // Send our second field
    sendField(out, "password", "toor");

    // Send another seperator
    out.write(boundaryBytes);

    // Send our file
    try(InputStream file = new FileInputStream("test.txt")) {
        sendFile(out, "identification", file, "text.txt");
    }

    // Finish the request
    out.write(finishBoundaryBytes);
}


// Do something with http.getInputStream()
Porphyritic answered 26/1, 2016 at 11:59 Comment(7)
This post is useful, but quite flawed. It took me 2 days to get it working. So to get it working you have to replace StandartCharsets.UTF8 with StandardCharsets.UTF_8 . boundaryBytes and finishBoundaryBytes need to get two additional hyphens which are NOT transmitted in the Content-Type, so boundaryBytes = ("--" + boundary + "\r\n").get... You also need to transmit the boundaryBytes once BEFORE the first field or the first field will be ignored!Caddell
Why out.write(finishBoundaryBytes); line need? http.connect(); will perform sending POST, isn't it?Nutty
It's relatively easier than what I expected considering it's Java :)Ordination
enigmatic \r\n\r\n means CRLF CRLF (carriage return + line feed). It creates 2x new line. First new line is to finish current line. Second line is to distinguish http header from http body in a request. HTTP is ASCII based protocol. This is the rule for inserting \r\n.Uranium
"Easy" In other languages this is like a one-line call. Why is it 8-12 lines in Java? qr.ae/TWAQA6Lava
@János out.write(finishBoundaryBytes) basically closes up our request - lookup multipart/form-data request structure. http.connect() explicitly fires a request, same thing is done implicitly by calling .getOuputStream()Cantonment
All usages of URLEncoder.encode should be removed in the sendFile and sendField helper methods, since this kind of encoding does not happen in multipart/form-dataSatisfaction
J
115
String rawData = "id=10";
String type = "application/x-www-form-urlencoded";
String encodedData = URLEncoder.encode( rawData, "UTF-8" ); 
URL u = new URL("http://www.example.com/page.php");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", type );
conn.setRequestProperty( "Content-Length", String.valueOf(encodedData.length()));
OutputStream os = conn.getOutputStream();
os.write(encodedData.getBytes());
Jan answered 24/7, 2010 at 11:49 Comment(6)
Important to notice: using anything other then String.getBytes() does not seem to work. For example, using a PrintWriter totally fails.Imperfective
and how to set 2 post data? Separate by colon, comma?Dancy
encode(String) is deprecated. You have to use encode(String, String), which specifies the encoding type. Example: encode(rawData, "UTF-8").Fingerling
You may want to following at the end. This would make sure the request is finished and server gets a chance to process the response: conn.getResponseCode();Vibes
For me, your solution wan't working for some reason but I knew its close (I've used similar before). https://mcmap.net/q/57911/-java-sending-http-parameters-via-post-method-easily worked well!Hamm
dont encode the entire string.. you have to encode just the value of each parameterLab
U
30

The first answer was great, but I had to add try/catch to avoid Java compiler errors.
Also, I had troubles to figure how to read the HttpResponse with Java libraries.

Here is the more complete code :

/*
 * Create the POST request
 */
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user", "Bob"));
try {
    httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e) {
    // writing error to Log
    e.printStackTrace();
}
/*
 * Execute the HTTP Request
 */
try {
    HttpResponse response = httpClient.execute(httpPost);
    HttpEntity respEntity = response.getEntity();

    if (respEntity != null) {
        // EntityUtils to get the response content
        String content =  EntityUtils.toString(respEntity);
    }
} catch (ClientProtocolException e) {
    // writing exception to log
    e.printStackTrace();
} catch (IOException e) {
    // writing exception to log
    e.printStackTrace();
}
Undervalue answered 29/4, 2013 at 17:37 Comment(2)
Sorry, but you didn't catch any errors, you introduced them. Catching exceptions in a place where you can't handle them is plain wrong and e.printStackTrace() doesn't handle anything.Colincolinson
java.net.ConnectException: Connection timed out: connectPaquette
R
17

A simple way using Apache HTTP Components is

Request.Post("http://www.example.com/page.php")
            .bodyForm(Form.form().add("id", "10").build())
            .execute()
            .returnContent();

Take a look at the Fluent API

Rives answered 30/11, 2013 at 16:22 Comment(1)
Just for convenience; the dependencies setup/info: hc.apache.org/httpcomponents-client-4.5.x/httpclient/… and hc.apache.org/httpcomponents-client-4.5.x/fluent-hc/…Spirituous
N
11

I suggest using Postman to generate the request code. Simply make the request using Postman then hit the code tab:

code tab

Then you'll get the following window to choose in which language you want your request code to be: request code generation

Noh answered 28/11, 2020 at 10:26 Comment(2)
Nice suggestions.Frap
nice, but it uses nonstandard OkHttpClient classes, and doesn't give you the imports you need :(Fluorescence
B
5

simplest way to send parameters with the post request:

String postURL = "http://www.example.com/page.php";

HttpPost post = new HttpPost(postURL);

List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", "10"));

UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(ent);

HttpClient client = new DefaultHttpClient();
HttpResponse responsePOST = client.execute(post);

You have done. now you can use responsePOST. Get response content as string:

BufferedReader reader = new BufferedReader(new  InputStreamReader(responsePOST.getEntity().getContent()), 2048);

if (responsePOST != null) {
    StringBuilder sb = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(" line : " + line);
        sb.append(line);
    }
    String getResponseString = "";
    getResponseString = sb.toString();
//use server output getResponseString as string value.
}
Bracknell answered 22/3, 2017 at 7:2 Comment(0)
R
5

Easy with java.net:

public void post(String uri, String data) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(uri))
        .POST(BodyPublishers.ofString(data))
        .build();

HttpResponse<?> response = client.send(request, BodyHandlers.discarding());
System.out.println(response.statusCode());

Here is more information: https://openjdk.java.net/groups/net/httpclient/recipes.html#post

Rodrick answered 30/9, 2021 at 9:39 Comment(0)
T
5

Since java 11, HTTP requests can be made by using java.net.http.HttpClient with less code.

    var values = new HashMap<String, Integer>() {{
        put("id", 10);
    }};
    
    var objectMapper = new ObjectMapper();
    String requestBody = objectMapper
            .writeValueAsString(values);
    
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://www.example.com/abc"))
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();
    
    HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());
    
    System.out.println(response.body());
Tape answered 1/8, 2022 at 12:8 Comment(0)
P
4

Using okhttp :

Source code for okhttp can be found here https://github.com/square/okhttp.

If you're writing a pom project, add this dependency

<dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.2.2</version>
    </dependency>

If not simply search the internet for 'download okhttp'. Several results will appear where you can download a jar.

your code :

import okhttp3.*;
        
import java.io.IOException;

public class ClassName{
        private void sendPost() throws IOException {
        
                // form parameters
                RequestBody formBody = new FormBody.Builder()
                        .add("id", 10)
                        .build();
        
                Request request = new Request.Builder()
                        .url("http://www.example.com/page.php")
                        .post(formBody)
                        .build();


                OkHttpClient httpClient = new OkHttpClient();
        
                try (Response response = httpClient.newCall(request).execute()) {
        
                    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
        
                    // Get response body
                    System.out.println(response.body().string());
                }
        }
    }
Preventive answered 14/9, 2021 at 12:18 Comment(0)
B
1

Call HttpURLConnection.setRequestMethod("POST") and HttpURLConnection.setDoOutput(true); Actually only the latter is needed as POST then becomes the default method.

Bangs answered 24/7, 2010 at 10:30 Comment(1)
it it HttpURLConnection.setRequestMethod() :)Carolyn
C
1

I recomend use http-request built on apache http api.

HttpRequest<String> httpRequest = HttpRequestBuilder.createPost("http://www.example.com/page.php", String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();

public void send(){
   String response = httpRequest.execute("id", "10").get();
}
Conformation answered 17/9, 2017 at 12:6 Comment(0)
R
1

Now we can use the new HTTP Client API (except on Android).

var uri = URI.create("https://httpbin.org/get?age=26&isHappy=true");
var client = HttpClient.newHttpClient();
var request = HttpRequest
        .newBuilder()
        .uri(uri)
        .version(HttpClient.Version.HTTP_2)
        .timeout(Duration.ofMinutes(1))
        .header("Content-Type", "application/json")
        .header("Authorization", "Bearer fake")
        .POST(BodyPublishers.ofString("{ title: 'This is cool' }"))
        .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());

The same request executed asynchronously:

var responseAsync = client
        .sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body)
        .thenAccept(System.out::println);
// responseAsync.join(); // Wait for completion

For sending form data as multipart (multipart/form-data) or url-encoded (application/x-www-form-urlencoded) format, see this solution.

See this article for examples and more information about HTTP Client API.

For Java standard library HTTP server, see this post.

Retrospect answered 5/1 at 6:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.