how to do a POST correctly with HttpUrlConnection? - java

I've been looking for methods to do send data to a web form or a web service, principally php servers, but there's a lot of answers with deprecated methods, I have to post a single value in a form, and another more elaborated webservice.
So there are like 3 questions:
I want to know if is posible to post data in a form and submit it, and if is possible how to do that. The form isn't a webservice, is a form to user's input (this one).
How to use correctly the HttpUrlConnection to call a webservice, (post data and get response), the webservice can use JSON or simple 2 string values like user and password.
Here's the code that I've found, basically:
private class PostTask extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
HttpURLConnection conn=null;
try {
URL url = new URL(params[0]);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
//conn.setReadTimeout(10000);
//conn.setConnectTimeout(15000);
//conn.setDoInput(true);
String body = "4";
conn.connect();
OutputStream output = new BufferedOutputStream(conn.getOutputStream());
output.write(body.getBytes());
output.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
assert conn != null;
conn.disconnect();
}
return true;
}
}

Yes is possible to pass data from a form as url params using HttpUrlConnection.
You 've almost got it
In a GET request, the parameters are sent as part of the URL.
In a POST request, the parameters are sent as a body of the request,
after the headers.
the way to do it:
public void sendForm(String formParam1, String formParam2, String formParam3){
String urlParameters = "param1="+formParam1+"&param2="+formParam2+"&param3="+formParam3;
try {
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
String request = "http://sicenet.com.mx/ws/index.php/inicio/editar_clave";
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 );
}
}catch (Exception e){
e.printStackTrace();
}
}
Not tested if it will work.
found in this StackOverFlow answer

Related

Java executing curl command using HttpURLConnection returns 204 (HTTP_NO_CONTENT)

I am using Java 11. I have the the following curl command, when I execute on the command line:
curl --location --request GET 'http://xxx.xxx.co.za:8080/document/details/Select+docId+From+%27Workflow+Club%2FCustomer+Invoices%27+where+recursive+%3D+true+and+invoice_number+%3D%271221669023%27' --header 'Authorization: Basic xxx'
Returns the following:
{errorMessage: 'PaperTrail API only available in enterprise edition'}
However, when I try execute the same URL in a Java application using HttpURLConnection, it returns a blank response.
private static final String USER_AGENT = "Mozilla/5.0";
private static final String GET_URL = "http://xxx.xxx.co.za:8080/document/details/";
private static final String GET_URL_QRY = "Select docId From 'Workflow Club/Customer Invoices' where recursive = true and invoice_number =':1'";
private static final String GET_AUTH_ENC = "Basic xxx";
#Override
public String getDocId(Long invoiceNumber) {
String get_url_qry = StringUtils.replace(GET_URL_QRY, ":1", Long.toString(invoiceNumber));
get_url_qry = URLEncoder.encode(get_url_qry, StandardCharsets.UTF_8);
final String get_url = GET_URL+get_url_qry;
try {
URL url = new URL(get_url);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", GET_AUTH_ENC);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = con.getResponseCode();
logger.info(get_url+" -> GET Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) { // success
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
String resp = response.toString();
logger.info(responseCode+" Response: '"+resp+"'.");
} else {
logger.error("GET request did not work (responseCode: "+responseCode+").");
}
} catch (MalformedURLException e) {
logger.error("MalformedURLException creating URL '"+get_url+"'. "+e.getMessage());
} catch (IOException e) {
logger.error("IOException creating connection from URL '"+get_url+"'. "+e.getMessage());
}
return null;
}
Outputs the following with a blank response:
204 Response: ''.
Question
How do I get the Java application to also return the same as the command line call?
UPDATE
I have a different POST url, that I need to call too, and I can call it successfully. So there's something wrong with my GET call.
private static final String USER_AGENT = "Mozilla/5.0";
E.g. GET call that returns a 204, with no content.
private String getDocId(Long invoiceNumber) {
String get_url_qry = StringUtils.replace(GET_URL_QRY, ":1", Long.toString(invoiceNumber));
get_url_qry = URLEncoder.encode(get_url_qry, StandardCharsets.UTF_8);
final String get_url = GET_URL+get_url_qry;
try {
URL url = new URL(get_url);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", GET_AUTH_ENC);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
Map<String,String> data = handleResponse(con);
return data.get("docId");
} catch (MalformedURLException e) {
logger.error("MalformedURLException creating URL '"+get_url+"'. "+e.getMessage());
} catch (IOException e) {
logger.error("IOException creating connection from URL '"+get_url+"'. "+e.getMessage());
}
return null;
}
The POST call, that returns a 200, and the expected content.
private String getDocLink(String docId) {
if (StringUtils.isNotBlank(docId)) {
try {
URL url = new URL(POST_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", GET_AUTH_ENC);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
byte[] postDataBytes = getPostData(docId);
con.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
con.setDoOutput(true);
con.getOutputStream().write(postDataBytes);
Map<String,String> data = handleResponse(con);
return data.get("url");
} catch (IOException e) {
logger.error("IOException creating connection from URL '"+POST_URL+"'. "+e.getMessage());
}
} else {
logger.error("No docId provided when trying to get a document link.");
}
return null;
}
So seeing the that POST call works, I think I must be doing something wrong with the GET call.
Did you try, setting the same user agent in your Java Code, cURL would use? something like curl/7.37.0?
As far as I can tell, that should be all, what differs. Aside cURL following redirects. But as there is no redirect, I guess it might be the User Agent making a difference.
There are a lot of server applications, behaving differently, when they are called by a browser (Like you make it think by setting the User-Agent to Mozilla/5.0), instead of some other application, like cURL.
From what you describe, the original call produces an error.
Assuming that you are also getting some form of error in the java code of your GET, you will catch the exception and simply log it. Then you will return null instead of a string, which will cause your response to have no content, i.e. 204.

How to get device Access token and perform multiple HTTP POST Request

I'm currently working on a project using an IoT platform " Thingsboard " where I've have created multiple devices, and I want to send data to each one of the devices from a JSON File, I'm using Rest Api to perform this request, but I've struggling for a while how to get the access token of my devices and parse each one of them in my request as a header param. I was just doing manually by getting them with Curl, but I want now to do it automatically. I know that Thingsboard has a Rest client Api written in java (https://thingsboard.io/docs/reference/rest-client/) so I've tried to use that in my script but I's not working. I'm new to working with Rest Api so if anybody can gie me a clue it would be so helpful.
here's a part of my code for the requests :
private static String token;
public String getToken() {
return token;
}
String paramValue = "param\\with\\backslash";
String yourURLStr = "http://host.com?param=" + java.net.URLEncoder.encode(paramValue, "UTF-8");
URL url2 = new URL("https://demo.thingsboard.io/api/v1/token/telemetry?token=$JWT_TOKEN");
HttpsURLConnection conn = (HttpsURLConnection) url2.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty(JWT_TOKEN_HEADER_PARAM, "Bearer" +token);
conn.setDoOutput(true);
OutputStream outStream = conn.getOutputStream();
OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream, "UTF-8");
outStreamWriter.write(list.toString());
outStreamWriter.flush();
outStreamWriter.close();
outStream.close();
String response = null;
System.out.println(conn.getResponseCode());
System.out.println(conn.getResponseMessage());
DataInputStream input1 = null;
input1 = new DataInputStream (conn.getInputStream());
while (null != ((response = input1.readLine()))) {
System.out.println(response);
input1.close ();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
If you are trying to get the JWT-token to authenticate the following java should work:
Request request = Request.Post("http://THINGSBOARD_URL/api/auth/login");
String body = "{\"username\":\"tenant#thingsboard.org\", \"password\":\"tenant\"}";
request.bodyString(body,ContentType.APPLICATION_JSON);
request.setHeader("Content-Type", "application/json");
request.setHeader("Accept", "application/json");
HttpResponse httpResponse = request.execute().returnResponse();
System.out.println(httpResponse.getStatusLine());
if (httpResponse.getEntity() != null) {
String html = EntityUtils.toString(httpResponse.getEntity());
System.out.println(html);
}
Don't get confused with JWT-Token for tenant authentication and Access-Token for Device Authentication.

Chromecast communication using JAVA/Android and Http

I'm trying to communicate with Chromecast using Http. I'm using this documentation about API methods and trying to execute an Youtube video on it. Following this answer to execute a post call, for now I have:
#Override
public void run() {
try {
String urlParameters = "v=oHg5SJYRHA0";
byte[] postData = urlParameters.getBytes();
int postLenght = postData.length;
//url is: new URL("http://192.168.25.99:8008/apps/YouTube")
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setInstanceFollowRedirects(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Content-Length", Integer.toString(postLenght));
urlConnection.setUseCaches(false);
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
wr.write(postData);
wr.flush();
wr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This command execute properly but nothing happening in Chromecast.
What am I doing wrong?
It works, I just forgot to call the response:
String responseMessage = urlConnection.getResponseMessage();
When I call this method, the video executes.

How can I pass parameters to uploadphoto task method?

I have a method which can be upload photo like this :
public class uploadphotos : ApiController
{
public Task<HttpResponseMessage> Post( )
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root =HostingEnvironment.MapPath("~/photos");//Burdaki app data klasoru degisecek
var provider = new MultipartFormDataStreamProvider(root);
// Read the form data and return an async task.
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
string fileName = file.LocalFileName;
string originalName = file.Headers.ContentDisposition.FileName;
FileInfo file2 = new FileInfo(fileName);
file2.CopyTo(Path.Combine(root, originalName.TrimStart('"').TrimEnd('"')), true);
file2.Delete();
//Trace.WriteLine(file.Headers.ContentDisposition.FileName);
// Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
}
It works fine. But I want to send parameters to that method, How can I do that?
Should I use like this:
public Task<HttpResponseMessage> Post( Par one , Par two )
{
...
...
...
On my android side :
URL url = new URL("myurl/par1/par2/"); // URL url = new URL("myurl") this works without parameters
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
...
...
...
...
But when I use this , I got 404 response from server.
How can I solve this issue?
thanks in advance
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(2);
nameValuePair.add(new BasicNameValuePair("param1", "param1"));
nameValuePair.add(new BasicNameValuePair("param1", "param1"));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
HttpResponse response = httpClient.execute(httpPost);
Take alook at here how to use HttpsURLConnection with the List<NameValuePair>
in your case;U need to write url with params with a function like this.
private String getQuery(List<NameValuePair> nameValuePair ) throws UnsupportedEncodingException
{
StringBuilder result = new StringBuilder();
boolean first = true;
for (NameValuePair pair : nameValuePair )
{
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(nameValuePair.getName(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(nameValuePair.getValue(), "UTF-8"));
}
return result.toString();
}
and later make a request.
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getQuery(params));
writer.flush();
writer.close();
os.close();
conn.connect();

Posting to a webservice using httpurlconnection

How come I am only allowed to make posts to .com url's but not .asmx url's? Im a bit confused as what I want to generally do is send xml content to a .asmx url web service eventually. Can anyone supply me with tips why this doesn't work, and how I can post to a .asmx file?
public class POSTSenderExample {
public String echoCuties(String query) throws IOException {
// Encode the query
String encodedQuery = URLEncoder.encode(query, "UTF-8");
// This is the data that is going to be send to itcuties.com via POST request
// 'e' parameter contains data to echo
String postData = "e=" + encodedQuery;
URL url = new URL("http://echo.itgeeeks.asmx");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", String.valueOf(postData.length()));
// Write data
OutputStream os = connection.getOutputStream();
os.write(postData.getBytes());
// Read response
StringBuilder responseSB = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ( (line = br.readLine()) != null)
responseSB.append(line);
// Close streams
br.close();
os.close();
return responseSB.toString();
}
// Run this example
public static void main(String[] args) {
try {
System.out.println(new POSTSenderExample().echoCuties("Hi there!"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Using "POST" is correct.
Instead of calling
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
you have to call
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
(if you are using utf-8 encoding which is probably the case).
You also have to set the SOAP Action in the http- Header:
connection.setRequestProperty("SOAPAction", SOAPAction);
You can find the SOAP Action eihter in the wsdl- file. What I did to find out all expected Parameters: I used a working WS Client, and traced the TCP traffic in order to find out the expected HTTP headers.

Categories