How to POST to node.js from applet? - java

I have an applet (not our choice, it's the MarioAI engine) that I'd like to connect to a node.js app that uses express...but I can't seem to get mongodb to accept the values I'm sending in my POST request through localhost. I keep getting 200 response from node, but 'undefined' from mongooose, which I suspect means the URLEncoder I'm using in Java is mangling the String I'm sending through somehow.
I read this:
Problem with Java Applet to connect our server to call a PHP file
and tried the following OutputStreamWriter call in Java:
//EvaluateFrustration() takes an int but should come back with a float value
String frustrationString = Double.toString(EvaluateFrustration(this.periods));
try {
URL url = new URL("http://127.0.0.1:8888/mario");
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
System.out.println(conn.getResponseCode());
conn.setUseCaches (false);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter writer;
writer = AccessController
.doPrivileged(new PrivilegedExceptionAction<OutputStreamWriter>() {
public OutputStreamWriter run() throws IOException {
return new OutputStreamWriter(conn.getOutputStream());
}
});
String data = URLEncoder.encode("frustrationValueFirstRound="
+ frustrationString,"UTF-8");
writer.write(data);
writer.flush();
} catch (Exception e) {
}
In the node app (using express and mongoose/mongodb), I wrote:
var express = require('express');
var mongoose = require('mongoose');
var Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var ExperimentSchema = new Schema({
experiment : ObjectId
, frustrationValueFirstRound : Number
});
mongoose.connect('mongodb://localhost/mariopaper');
mongoose.model('Experiment', ExperimentSchema);
var Experiment = mongoose.model('Experiment');
app.post('/mario', function(req, res){
var exp = new Experiment();
exp.frustrationValueFirstRound = req.body.frustrationValueFirstRound;
exp.save(function(err){ if (err) { throw err; }
res.send('ok');
});
For reference, I'd like to point out that this curl call works just fine:
curl -d "frustrationValueFirstRound=99" http://localhost:8888/mario
Anyone have any ideas whether I've simply written the POST wrong in Java, or perhaps I'm missing something in how URLEncoder.encode() works?

I think that's because you don't have the body-parser node module, that "Parse incoming request bodies in a middleware before your handlers, available under the req.body property."
Try this (after installing body-parser module):
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
var Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var ExperimentSchema = new Schema({
experiment : ObjectId
, frustrationValueFirstRound : Number
});
mongoose.connect('mongodb://localhost/mariopaper');
mongoose.model('Experiment', ExperimentSchema);
var Experiment = mongoose.model('Experiment');
app.post('/mario', function(req, res){
console.log(req.body); // Is there something here ?
var exp = new Experiment();
exp.frustrationValueFirstRound = req.body.frustrationValueFirstRound;
exp.save(function(err){ if (err) { throw err; }
res.send('ok');
});
source : https://github.com/expressjs/body-parser

Related

Converting HTTP POST from curl (PHP) to HttpURLConnection (Java)

I tried to convert the below PHP code (taken from https://www.cryptocoincharts.info/tools/api) to java
// define pairs
$post = array("pairs" => "ltc_usd,ppc_btc");
// fetch data
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://api.cryptocoincharts.info/tradingPairs");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
$rawData = curl_exec($curl);
curl_close($curl);
// decode to array
$data = json_decode($rawData);
// show data
echo "<pre>";
foreach ($data as $row)
{
echo "Price of ".$row->id.": ".$row->price."\n";
echo "Trade this pair on ".$row->best_market."\n";
}
echo "</pre>";
Java Code
URL url = new URL("http://api.cryptocoincharts.info/tradingPairs");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// CURLOPT_POST
con.setRequestMethod("POST");
// CURLOPT_FOLLOWLOCATION
con.setInstanceFollowRedirects(true);
String postData = "ltc_usd,ppc_btc";
con.setRequestProperty("Content-length", String.valueOf(postData.length()));
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream output = new DataOutputStream(con.getOutputStream());
output.writeBytes(postData);
output.close();
// "Post data send ... waiting for reply");
int code = con.getResponseCode(); // 200 = HTTP_OK
System.out.println("Response (Code):" + code);
System.out.println("Response (Message):" + con.getResponseMessage());
// read the response
DataInputStream input = new DataInputStream(con.getInputStream());
int c;
StringBuilder resultBuf = new StringBuilder();
while ( (c = input.read()) != -1) {
resultBuf.append((char) c);
}
input.close();
System.out.println("resultBuf.toString() " + resultBuf.toString());
As per the API, after converting this to java I should get only the details of LTC and PPC details. Instead I am getting a strange Json with all trading pairs.
2 $post = array("pairs" => "ltc_usd,ppc_btc"); Posted the PHP code as I am not known the exact equivalent in Java
Could you please point out if my conversion from PHP to Java is correct ?
As far as I see, the main difference between the two implementation is related to the $post variable.
In the PHP implementation $post is a key/value array but in Java I only see the value part.
I suggest to change the postData variable content into pairs=ltc_usd,ppc_btc
You didn't mentioned key part, only value is mentioned. And when we fetch data from PHP API, we have an associative array. If u want to display the output, u need to know the key and value of the particular associative array.
And the InputStream and OutputStream should be inside try-resources
you can try curl-to-java lib to convert curl php code to java code
https://github.com/jeffreyning/curl-to-java
demo like this
public Object curl(String url, Object postData, String method) {
CurlLib curl = CurlFactory.getInstance("default");
ch = curl.curl_init();
curl.curl_setopt(ch, CurlOption.CURLOPT_CONNECTTIMEOUT, 1000);
curl.curl_setopt(ch, CurlOption.CURLOPT_TIMEOUT, 5000);
curl.curl_setopt(ch, CurlOption.CURLOPT_SSL_VERIFYPEER, false);
curl.curl_setopt(ch, CurlOption.CURLOPT_SSL_VERIFYHOST, false);
String postDataStr = "key1=v1";
curl.curl_setopt(ch, CurlOption.CURLOPT_CUSTOMREQUEST, "POST");
curl.curl_setopt(ch, CurlOption.CURLOPT_POSTFIELDS, postDataStr);
curl.curl_setopt(ch, CurlOption.CURLOPT_URL, "https://xxxx.com/yyy");
Object html = curl.curl_exec(ch);
Object httpCode = curl.curl_getinfo(ch, CurlInfo.CURLINFO_HTTP_CODE);
if (httpCode != null && 200 == Integer.valueOf(httpCode.toString())) {
return null;
}
return html;
}

Err :java.net.ConnectException: failed to connect to /10.0.2.2 (port 8000): connect failed:

I am trying to connect to Android emulator via Android Studio IDE. I am on the Mac running PHP server using command php -S localhost:8000(because this worked in IoS using XCODE IDE). I have an Async task I want to run to wrie data to SQL server via addtoDB method. Several posts suggested using 10.0.2.2. And i used it. However I still get the same error. The following is my code. It is very simple but does not work. Also I cannot ping 10.0.2.2.I tried localhost and that gave same error. At one point it did work by saying it is connected to the php server but it always gave (unexpected end of file) on the PHP window. The PHP code is show after the Java code.
I would like to say that on IoS this works everytime and I have successfully ported the app ot iphone and using it. What am I doing wrong here.
Thanks for your help in advance.
Ramesh
class doHTTPPost extends AsyncTask<Void,Void,String> {
/*
private String Url;
private Integer tos;
public doHTTTPPost(String url, Integer typeOfService) {
Url = url;
tos = typeOfService;
}
*/
protected String doInBackground(Void... params) {
//now call your ipify method which is doing the networking or calling a method that might be doing the networkign
//getContents("http://localhost:8080");
String result ="";
result = addToDb();
return result;
}
private String addToDb() {
String urlParameters = "Fname=Ram&Lname=Ramesh&Msisdn=6785459898";
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
//String request = "http://example.com/index.php";
//let myUrl = URL(string: "http://localhost:8000/serviceadd-all-good.php/")
String request = "http://10.0.2.2:8000/serviceaddAndroid.php/";
URL url=null;
try {
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 );
DataOutputStream wr = new DataOutputStream( conn.getOutputStream());
wr.write( postData );
} catch (IOException e) {
System.out.println("Err :"+e);
Log.i("Add","Error");
return("Error");
}
Log.i("Add","Done");
return("Done");
}
The PHP code is
<?php
$dir = 'sqlite:/Users/lakshmi/Documents/ServiceTesting.sqlite';
$dbh = new PDO($dir) or die("cannot open the database");
// Read request parameters
$fname = $_REQUEST["Fname"];
$lname = $_REQUEST["Lname"];
$msisdn = $_REQUEST["Msisdn"];
//$dbh->exec( "INSERT INTO Service_Testing (ID, Status, Tech) VALUES ('$id','$status','$tech')");
$dbh->exec( "INSERT INTO TestWithAndroid (Fname, Lname, Msisdn ) VALUES ('$fname','$lname','$msisdn')");
//$dbh->exec("INSERT INTO Result (Serial, Testid, Result) VALUES ('$serial','$testid','$result')");
//echo "Row inserted \n";
//$dbh->exec('INSERT INTO Result (Serial, Testid, Result) VALUES (5,"st3","Fail")');
//echo "Row inserted \n";
// Send data back
//echo json_encode($returnValue);
?>

Persistent HTTP-connection from Android to Node.js server

I'm trying to implement a little communication scheme handling HTTP-requests from an Android device to a Node.js server. With the current code the Android side closes the connection after receiving the response from the header.
Java:
public String doInBackground(Void... params) {
URL url = new URL("http://" + mServer.getHost() + ":" + mServer.getPort() + "/" + mPath);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setConnectTimeout(TIMEOUT);
http.setRequestMethod("POST");
http.setDoOutput(true);
http.connect();
OutputStream out = http.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(out);
writer.write(mJson);
writer.flush();
writer.close();
mResponseCode = http.getResponseCode();
if (mResponseCode != 200) {
http.disconnect();
return "";
}
InputStreamReader in = new InputStreamReader(http.getInputStream());
BufferedReader br = new BufferedReader(in);
char[] chars = new char[BUF_SIZE];
int size = br.read(chars);
String response = new String(chars).substring(0, size);
//http.disconnect();
return response;
}
Node:
this.socket = http.createServer((req, res) => {
req.on('data', (chunk) => {
this.log.info("DATA");
obj = JSON.parse(chunk.toString());
});
req.on('close', () => {
this.log.info("CLOSE");
});
req.on('connection', (socket) => {
this.log.info("CONNECTION");
});
req.on('end', () => {
this.log.info("END");
});
});
this.socket.listen(this.port, this.host);
Further the connection event on the Node side is never called, every request is directly piped into the data event.
Is there a way to establish a persistent HTTP-connection such that the Node server can keep track of it while the connection is running until the Android side closes it again?
Socket.io seems to be a reasonable library to achieve persistent connections from Android to a Node.js server.

HttpURLConnection sending JSON POST request to Apache/PHP

I'm struggling with HttpURLConnection and OutputStreamWriter.
The code actually reaches the server, as I do get a valid error
response back. A POST request is made, but no data is received
server-side.
Any hints to proper usage of this thingy is highly appreciated.
The code is in an AsyncTask
protected JSONObject doInBackground(Void... params) {
try {
url = new URL(destination);
client = (HttpURLConnection) url.openConnection();
client.setDoOutput(true);
client.setDoInput(true);
client.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
client.setRequestMethod("POST");
//client.setFixedLengthStreamingMode(request.toString().getBytes("UTF-8").length);
client.connect();
Log.d("doInBackground(Request)", request.toString());
OutputStreamWriter writer = new OutputStreamWriter(client.getOutputStream());
String output = request.toString();
writer.write(output);
writer.flush();
writer.close();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
Log.d("doInBackground(Resp)", result.toString());
response = new JSONObject(result.toString());
} catch (JSONException e){
this.e = e;
} catch (IOException e) {
this.e = e;
} finally {
client.disconnect();
}
return response;
}
The JSON I'm trying to send:
JSONObject request = {
"action":"login",
"user":"mogens",
"auth":"b96f704fbe702f5b11a31524bfe5f136efea8bf7",
"location":{
"accuracy":25,
"provider":"network",
"longitude":120.254944,
"latitude":14.847808
}
};
And the response I get from the server:
JSONObject response = {
"success":false,
"response":"Unknown or Missing action.",
"request":null
};
And the response I should have had:
JSONObject response = {
"success":true,
"response":"Welcome Mogens Burapa",
"request":"login"
};
The server-side PHP script:
<?php
$json = file_get_contents('php://input');
$request = json_decode($json, true);
error_log("JSON: $json");
error_log('DEBUG request.php: ' . implode(', ',$request));
error_log("============ JSON Array ===============");
foreach ($request as $key => $val) {
error_log("$key => $val");
}
switch($request['action'])
{
case "register":
break;
case "login":
$response = array(
'success' => true,
'message' => 'Welcome ' . $request['user'],
'request' => $request['action']
);
break;
case "location":
break;
case "nearby":
break;
default:
$response = array(
'success' => false,
'response' => 'Unknown or Missing action.',
'request' => $request['action']
);
break;
}
echo json_encode($response);
exit;
?>
And the logcat output in Android Studio:
D/doInBackground(Request)﹕ {"action":"login","location":{"accuracy":25,"provider":"network","longitude":120.254944,"latitude":14.847808},"user":"mogens","auth":"b96f704fbe702f5b11a31524bfe5f136efea8bf7"}
D/doInBackground(Resp)﹕ {"success":false,"response":"Unknown or Missing action.","request":null}
If I append ?action=login to the URL I can get a success response from the server. But only the action parameter registers server-side.
{"success":true,"message":"Welcome ","request":"login"}
The conclusion must be that no data is transferred by URLConnection.write(output.getBytes("UTF-8"));
Well, data get transferred after all.
Solution offered by #greenaps does the trick:
$json = file_get_contents('php://input');
$request = json_decode($json, true);
PHP script above updated to show the solution.
echo (file_get_contents('php://input'));
Will show you the json text. Work with it like:
$jsonString = file_get_contents('php://input');
$jsonObj = json_decode($jsonString, true);
try to use DataOutputStream instead of OutputStreamWriter.
DataOutputStream out = new DataOutputStream(_conn.getOutputStream());
out.writeBytes(your json serialized string);
out.close();
I've made server tell me what it got from me.
Request Headers and POST Body
<?php
$requestHeaders = apache_request_headers();
print_r($requestHeaders);
print_r("\n -= POST Body =- \n");
echo file_get_contents( 'php://input' );
?>
Works like a charm)
The code actually reaches the server, as I do get a valid error
response back. A POST request is made, but no data is received
server-side.
got this same situation, and come to #greenapps answer.
you should know what server recieved from 'post request'
what i do first on the server side :
echo (file_get_contents('php://input'));
then print/Toast/show message response on the client side. make sure its correct form, like :
{"username": "yourusername", "password" : "yourpassword"}
if the response like this (because you post the request with yourHashMap.toString()) :
{username=yourusername,password=yourpassword}
instead using .toString(), use this method instead to turn HashMap into String :
private String getPostDataString(HashMap<String, String> postDataParams) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Map.Entry<String,String> entry : postDataParams.entrySet()){
if(first){
first = false;
}else{
result.append(",");
}
result.append("\"");
result.append(entry.getKey());
result.append("\":\"");
result.append(entry.getValue());
result.append("\"");
}
return "{" + result.toString() + "}";
}

Processing a website by using POST data and cookies

I try to access an ASPX-website where subsequent pages are returned based on
post data. Unfortunately all my attempts to get the following pages fail.
Hopefully, someone here has an idea where to find the error!
In step one I read the session ID from the cookie as well as the value of the
viewstate variable in the returned html page. Step two intends to send it
back to the server to get the desired page.
Sniffing the data in the webbrowser gives
Host=www.geocaching.com
User-Agent=Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100618
Iceweasel/3.5.9 (like Firefox/3.5.9)
Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language=en-us,en;q=0.5
Accept-Encoding=gzip,deflate
Accept-Charset=ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive=300
Connection=keep-alive
Referer=http://www.geocaching.com/seek/nearest.aspx?state_id=149
Cookie=Send2GPS=garmin; BMItemsPerPage=200; maprefreshlock=true; ASP.
NET_SessionId=c4jgygfvu1e4ft55dqjapj45
Content-Type=application/x-www-form-urlencoded
Content-Length=4099
POSTDATA=__EVENTTARGET=ctl00%24ContentBody%24pgrBottom%
24lbGoToPage_3&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPD[...]2Xg%3D%
3D&language=on&logcount=on&gpx=on
Currently, my script looks like this
import java.net.*;
import java.io.*;
import java.util.*;
import java.security.*;
import java.net.*;
public class test1 {
public static void main(String args[]) {
// String loginWebsite="http://geocaching.com/login/default.aspx";
final String loginWebsite = "http://www.geocaching.com/seek/nearest.aspx?state_id=159";
final String POST_CONTENT_TYPE = "application/x-www-form-urlencoded";
// step 1: get session ID from cookie
String sessionId = "";
String viewstate = "";
try {
URL url = new URL(loginWebsite);
String key = "";
URLConnection urlConnection = url.openConnection();
if (urlConnection != null) {
for (int i = 1; (key = urlConnection.getHeaderFieldKey(i)) != null; i++) {
// get ASP.NET_SessionId from cookie
// System.out.println(urlConnection.getHeaderField(key));
if (key.equalsIgnoreCase("set-cookie")) {
sessionId = urlConnection.getHeaderField(key);
sessionId = sessionId.substring(0, sessionId.indexOf(";"));
}
}
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
// get the viewstate parameter
String aLine;
while ((aLine = in.readLine()) != null) {
// System.out.println(aLine);
if (aLine.lastIndexOf("id=\"__VIEWSTATE\"") > 0) {
viewstate = aLine.substring(aLine.lastIndexOf("value=\"") + 7, aLine.lastIndexOf("\" "));
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(sessionId);
System.out.println("\n");
System.out.println(viewstate);
System.out.println("\n");
// String goToPage="3";
// step2: post data to site
StringBuilder htmlResult = new StringBuilder();
try {
String encoded = "__EVENTTARGET=ctl00$ContentBody$pgrBottom$lbGoToPage_3" + "&" + "__EVENTARGUMENT=" + "&"
+ "__VIEWSTATE=" + viewstate;
URL url = new URL(loginWebsite);
URLConnection urlConnection = url.openConnection();
urlConnection = url.openConnection();
// Specifying that we intend to use this connection for input
urlConnection.setDoInput(true);
// Specifying that we intend to use this connection for output
urlConnection.setDoOutput(true);
// Specifying the content type of our post
urlConnection.setRequestProperty("Content-Type", POST_CONTENT_TYPE);
// urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Cookie", sessionId);
urlConnection.setRequestProperty("Content-Type", "text/html");
DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream());
out.writeBytes(encoded);
out.flush();
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String aLine;
while ((aLine = in.readLine()) != null) {
System.out.println(aLine);
}
} catch (MalformedURLException e) {
// Print out the exception that occurred
System.err.println("Invalid URL " + e.getMessage());
} catch (IOException e) {
// Print out the exception that occurred
System.err.println("Unable to execute " + e.getMessage());
}
}
}
Any idea what's wrong? Any help is very appreciated!
Update
Thank you for the fast reply!
I switched to use the HttpURLConnection instead of the URLConnection which implements the setRequestMethod(). I also corrected the minor mistakes you mentioned, e.g. removed the obsolete first setRequestProperty call.
Unfortunately this doesn’t change anything... I think I set all relevant parameters but still get the first page of the list, only. It seems that the "__EVENTTARGET=ctl00$ContentBody$pgrBottom$lbGoToPage_3" is ignored. I don't have any clues why.
Internally, the form on the website looks like this:
<form name="aspnetForm" method="post" action="nearest.aspx?state_id=159" id="aspnetForm">
It is called by the following javascript:
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
Hopefully, this helps to find a solution?
Greetings
maik.
Do you actually want to GET or POST? If you want to POST, then you may need the setRequestMethd() line.
You're setting Content-Type twice -- I think you may need to combine these into one line.
Then, don't close the output stream before you try and read from the input stream.
Other than that, is there any more logging you can put in/clues you can give as to what way it's going wrong in?
Hey use following code
String userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0";
org.jsoup.nodes.Document jsoupDoc = Jsoup.connect(url).timeout(15000).userAgent(userAgent).referrer("http://calendar.legis.ga.gov/Calendar/?chamber=House").ignoreContentType(true)
.data("__EVENTTARGET", eventtarget).data("__EVENTARGUMENT", eventarg).data("__VIEWSTATE", viewState).data("__VIEWSTATEGENERATOR", viewStateGenarator)
.data("__EVENTVALIDATION", viewStateValidation).parser(Parser.xmlParser()).post();

Categories

Resources