Proper way to make PHP "POST" statements in Java (Android-Studio) - java

I'm trying to post two strings on a PHP web server. First, I use this relevant part of my PHP script, which does work in other projects with other languages.
function open($db){
$name = $_POST['name'];
$pwd = $_POST['pwd'];
// Prepare SQL statement
$statement = $db->prepare("SELECT * FROM `table` WHERE `name`=?");
$statement->bind_param("s", $name);
$statement->execute();
$result = $statement->get_result();
$row = mysqli_fetch_assoc($result);
if($result->num_rows > 0){
$hashed_pwd = $row['pwd'];
}
else{
echo 'No result!';
$statement->close();
return;
}
if(password_verify($pwd, $hashed_pwd)){
echo 'Success!';
}
else {
echo 'Wrong password!';
}
// Close SQL Statement
$statement->close();
}
In Java, I face multiple problems. The function gets called, when pressing the “Open” button:
public void onOpenClick(View v){
final String name = "someString";
final String pwd = "someString";
new Thread(new Runnable() {
#Override
public void run() {
try {
//Add the action to the original URL
urlString += "?action=open";
URL url = new URL(urlString);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
String info = "name=" + name + "pwd=" + pwd;
con.setRequestMethod("POST");
con.setDoOutput(true);
con.getOutputStream().write(info.getBytes("UTF-8"));
con.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
answer = in.readLine();
}catch (Exception e){
System.out.println(e.toString());
answer = e.toString();
}
}
}).start();
}
Is using a Thread the correct way to make a PHP requests?
Furthermore, I always get as answer “No result!” and if I change the echo statement in the PHP file to $name, nothing returns at all.
In conclusion, the connection to my server is successful, the POST statement is not. I tried different approaches, none of them worked.
If I press the button again, I do not get any response at all and answer is null or empty.
Edit
I tried adding following statements as well:
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
And:
StringBuilder postData = new StringBuilder();
postData.append(URLEncoder.encode("name", "UTF-8"));
postData.append("=");
postData.append(URLEncoder.encode(name, "UTF-8"));
postData.append(URLEncoder.encode("pwd", "UTF-8"));
postData.append("=");
postData.append(URLEncoder.encode(pwd, "UTF-8"));
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
con.setRequestMethod("POST");
con.setInstanceFollowRedirects(false);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
con.setDoOutput(true);
con.setUseCaches(false);

I had the same issue when trying to call a php server from javascript.
I figured out I needed to add the Content-Type header correctly.
'Content-Type': 'application/x-www-form-urlencoded'

Related

error while sending data from java code to PHP in localhost using HTTPPost request

This is my java code to send data through HTTPPost request:
import java.io.*;
import java.net.*;
class HttpURLConnectionEx{
public static void main(String[] args) throws Exception{
URL targetURL = new URL("http://localhost/JAVA/post.php");
HttpURLConnection conn =(HttpURLConnection) targetURL.openConnection();
String body= "fName="+ URLEncoder.encode("value1","UTF-8")+"&lName=" + URLEncoder.encode("value2","UTF-8");
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "UTF-8");
conn.setRequestProperty("Content-Length", Integer.toString(body.length()));
try
{
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(body);
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while((line = rd.readLine()) != null) {
System.out.println(line);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
This is my PHP code present in localhost:
<?php
$data = $_POST["fName"];
$dbc = mysqli_connect('localhost','root','root123','JAVA')
or die("error connecting to mysql server");
$query = "INSERT INTO insert_table(data) VALUES('".$data."')";
if($query){
echo "data inserted sucessfully";
}
$result = mysqli_query($dbc,$query) or die("error querying database");
?>
This is the output i 'm getting when i run it in commandline:
A flush after the write is required.
out.flush();
edit
Undefined index: fName
The php error is clear enough, isn't? The $_POST array doesn't contain your POST variables.
First I've checked on php side the content of the post with var_dump($_POST) and:
/* save the raw post to a file */
file_put_contents('/tmp/post.txt', file_get_contents('php://input'));
Both were empty, so I used wireshark to check the HTTP/POST content, it was done but with Content-Length: 0 and without body.
Few googles to something similar to your code and I noticed the flush that mean OutputStreamWriter is buffered and at the time of the post request the output could be not written (sent to the server) or only partially, a good reason for zero content-length.
At this point I think you don't need to use conn.setRequestProperty for "Content-Length", it should be updated according with your buffer content length.

Send POST data from JSP page to remote PHP server (and get an answer)

I'm trying to send some data from a JSP page to a PHP one (which should execute some code and return a success message).
I'm using this java function to make some tests:
public String excutePost(String targetURL, String urlParameters)
{
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 ();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
String urlParameters =
"var=" + URLEncoder.encode("varcontent", "UTF-8");
out.println(excutePost("remoteurl",urlParameters));
Now if i run the page i get the response "null" and none of the code in the php page is executed.
Am I doing something wrong? How can I allow the php page to run the code in it?
Isn't a simple echo $_POST['var'] enough to send the data back to the jsp page?
EDIT: I tried to see if the php page is receiving something by writing the posted variable in a file. But nothing is written in it.
$file = 'debug.txt';
echo file_put_contents($file, $_POST['var']);
and here is the exception i'm getting..
java.net.SocketException: Connection reset
No, an echo is not enough. Put $_POST['var'] in say a text file and serve the updated text file (Edit the text file each time you need to keep track of $_POST['var']). Alternatively you can put it in some DB and check for changes.

set methods aren't working for HttpsURLConnection

I'm trying to make a rest request in java. I tested the web service using RestClient in Firefox and it works great.
When i try to modify the HttpsUrlConnection instance in java the values aren't changing and i get a 500 response code.
Here's my code:
public String getAuthToken() throws IOException {
URL url =new URL("https://webserviceurl"); // webservice url is the url of the webservice
String data = URLEncoder.encode("username") + "=" + URLEncoder.encode("myusername","UTF-8");
data+= "&" + URLEncoder.encode("password") + "=" + URLEncoder.encode("pass","UTF-8");
HttpsURLConnection conn =(HttpsURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setHostnameVerifier(new AllowAllHostnameVerifier()); //this works HostName verifier changes
conn.setRequestMethod("POST"); // this doens't work. requestMethod is still set to GET
conn.setDoOutput(true); // this doesnt work. DoOutput still set on false
conn.setRequestProperty("Content-Type", "application/json"); // doens't work either
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
wr.write(data);
wr.flush();
wr.close();
//conn has a 500 response code
if (conn.getResponseCode()==200)
{
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader rd = new BufferedReader(isr);
String token = rd.readLine();
rd.close();
return token;
}
else
return null;
}
I'm stucked at this point and cannot find anything to make this work.
Thank you!
I actually think it's a bug with HttpsURLConnection. As i changed it to a HttpURLConnection object everything works just fine.

Preemptive Basic Auth with HttpUrlConnection?

What is the best way to use preemptive basic http authentication using HttpUrlConnection. (Assume for now I can't use HttpClient).
EDIT for clarification: I'm setting the un/pw correctly in the request header using Base64 encoding. Are there any additional flags or properties that need to be set, or is the fact that I'm setting the basic auth headers for the request all that is needed for preemptive basic auth?
If you are using Java 8 or later, java.util.Base64 is usable:
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
String encoded = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8)); //Java 8
connection.setRequestProperty("Authorization", "Basic "+encoded);
Then use the connection as normal.
If you're using Java 7 or lower, you'll need a method to encode a String to Base64, such as:
byte[] message = (username+":"+password).getBytes("UTF-8");
String encoded = javax.xml.bind.DatatypeConverter.printBase64Binary(message);
Yes, that's all you have to do in order to use Basic Auth. The code above to set the Request Property should be done immediately after opening the connection and before getting the Input or Output streams.
Incidentally, in case someone else runs into the same, the android problem, is also present if you use org.apache.commons.codec.binary.Base64 and do Base64.encodeBase64String(). You need to do Base64.encodeBase64() and get a byte[] then construct the string.
It caught me offguard entirely that the results would be different for the line ending between those two methods.
You can use java.net.Authenticator to configure basic auth. globally for every request send by your application, see :
http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html
http://developer.android.com/reference/java/net/Authenticator.html#getPasswordAuthentication()
you need to do this just copy paste it be happy
HttpURLConnection urlConnection;
String url;
// String data = json;
String result = null;
try {
String username ="danish.hussain#gmail.com";
String password = "12345678";
String auth =new String(username + ":" + password);
byte[] data1 = auth.getBytes(UTF_8);
String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
//Connect
urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "Basic "+base64);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
JSONObject obj = new JSONObject();
obj.put("MobileNumber", "+97333746934");
obj.put("EmailAddress", "danish.hussain#dhl.com");
obj.put("FirstName", "Danish");
obj.put("LastName", "Hussain");
obj.put("Country", "BH");
obj.put("Language", "EN");
String data = obj.toString();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(data);
writer.close();
outputStream.close();
int responseCode=urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
}else {
// return new String("false : "+responseCode);
new String("false : "+responseCode);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
I was having this problem too.
And Now I have solved this problem.
My code is :
URL url = new URL(stringUrl);
String authStr = "MyAPIKey"+":"+"Password";
System.out.println("Original String is " + authStr);
// encode data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(authStr .getBytes());
String authEncoded = new String(bytesEncoded);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Basic "+authEncoded);
It may help many others.
Best of luck.
Regarding the Base64 encoding problem, I found this library: http://sourceforge.net/projects/migbase64/
I have not fully vetted it but I am using it for the Basic Authentication solution shown above (as well as for image encoding/decoding), and it works well. It provides a parameter for whether or not to include the newline.

URLConnection sometimes returns empty string response?

I'm making an http GET request. It works in about 70% of my attempts. For some reason, I sometimes get no response string from a successful connection. I just setup a button in my app which keeps firing the code below. One call might fail to reply with a string, the next call works fine:
private onButtonClick() {
try {
doit();
} catch (Exception ex) {
...
}
}
public void doit() throws Exception {
URL url = new URL("http://www.example.com/service");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setAllowUserInteraction(false);
connection.setReadTimeout(30 * 1000);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Authorization",
"Basic " + Base64.encode("username" + ":" + "password"));
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
StringBuilder sb = new StringBuilder();
while ((line = in.readLine()) != null) {
sb.append(line);
}
in.close();
connection.disconnect();
// Every so often this prints an empty string!
System.out.println(sb.toString());
}
am I doing something wrong here? It seems like maybe I'm not closing the connection properly from the last call somehow and the response gets mangled or something? I am also calling doit() from multiple threads simultaneously, but I thought the contents of the method are thread-safe, same behavior though,
Thanks
Thanks
That method looks fine. It's reentrant, so calls shouldn't interfere with each other. It's probably a server issue, either deliberate throttling or just a bug.
EDIT: You can check the status code with getResponseCode.
For checking ResponseCode:
BufferedReader responseStream;
if (((HttpURLConnection) connection).getResponseCode() == 200) {
responseStream = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
} else {
responseStream = new BufferedReader(new InputStreamReader(((HttpURLConnection) connection).getErrorStream(), "UTF-8"));
}
For empty content resposneCode is 204. So if u can get empty body just add one more "if" with 204 code.
We also came across with the similar scenario, I came across the following solution for this issue:
- Setting up a user agent string on URLConnection object.
URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
more details

Categories