How to send post request with x-www-form-urlencoded body

Request in postman

How in java, can I send a request with x-www-form-urlencoded header. I don't understand how to send a body with a key-value, like in the above screenshot.

I have tried this code:

String urlParameters =
cafedra_name+ data_to_send;
URL url;
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");


connection.setRequestProperty("Content-Length", "" +
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");


connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);


//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();

But in the response, I don't receive the correct data.

225967 次浏览

As you set application/x-www-form-urlencoded as content type so data sent must be like this format.

String urlParameters  = "param1=data1&param2=data2&param3=data3";

Sending part now is quite straightforward.

byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
String request = "<Url here>";
URL url = new URL( request );
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "utf-8");
conn.setRequestProperty("Content-Length", Integer.toString(postDataLength ));
conn.setUseCaches(false);
try(DataOutputStream wr = new DataOutputStream(conn.getOutputStream())) {
wr.write( postData );
}

Or you can create a generic method to build key value pattern which is required for application/x-www-form-urlencoded.

private String getDataString(HashMap<String, String> params) throws UnsupportedEncodingException{
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}

For HttpEntity, the below answer works

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);


MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("email", "first.last@example.com");


HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);


ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );

For reference: How to POST form data with Spring RestTemplate?

string urlParameters = "param1=value1&param2=value2";
string _endPointName = "your url post api";


var httpWebRequest = (HttpWebRequest)WebRequest.Create(_endPointName);


httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
httpWebRequest.Headers["ContentType"] = "application/x-www-form-urlencoded";


System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) =>
{
return true;
};




using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(urlParameters);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();


using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}

Building off of Navoneel's answer, I like to use StreamEx's EntryStream.

Here is Naveoneel's method re-written.

private String getDataString(HashMap<String, String> params)
{
return EntryStream.
of(data).
mapKeys(key -> URLEncoder.encode(key, StandardCharsets.UTF_8)).        // Encode the keys
mapValues(value -> URLEncoder.encode(value, StandardCharsets.UTF_8)).  // Encode the values
join("=").                                                             // Create a key=value
joining("&");                                                          // Assemble into key1=value1&key2=value2...
}

Use Java 11 HttpClient

The HTTP Client was added in Java 11. It can be used to request HTTP resources over the network. It supports HTTP/1.1 and HTTP/2, both synchronous and asynchronous programming models, handles request and response bodies as reactive-streams, and follows the familiar builder pattern.

https://openjdk.java.net/groups/net/httpclient/intro.html

HttpClient client = HttpClient.newHttpClient();;
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(targetUrl))
.POST(urlParameters)
.headers("Content-Type", "application/x-www-form-urlencoded")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Problem with the Response!

I had a similar issue when I was sending the request of media type application/x-www-form-urlencoded from Postman I was receiving a correct response.

However, when sending the request using code, I was receiving jargon somewhat like:

�-�YO�`:ur���g�
.n��l���u)�i�h3J%Gl�?����k



What I tried:

Out of frustration for multiple days tried all the possible solutions from changing character sets to changing header values to code changes and whatnot.


Solution lies in Postman.

Code Generation

Select Java-OkHttp

enter image description here

Copy the code and paste it into IDE.

That's it.

Reference for HttpOk: https://www.vogella.com/tutorials/JavaLibrary-OkHttp/article.html