Parsing post data in phantomjs - javascript

I am working with the POSTMAN extension to chrome and am trying to send a post request to phantomjs I have managed to send a post request to a phantomjs server script by setting postman as in the attached screenshot
My phantomjs script is as follows:
// import the webserver module, and create a server
var server = require('webserver').create();
var port = require('system').env.PORT || 7788;
console.log("Start Application");
console.log("Listen port " + port);
// Create serever and listen port
server.listen(port, function(request, response) {
console.log("request method: ", request.method); // request.method POST or GET
if(request.method == 'POST' ){
console.log("POST params should be next: ");
console.log(request.headers);
code = response.statusCode = 200;
response.write(code);
response.close();
}
});
when I run phantomjs at the command line , here is the output:
$ phantomjs.exe myscript.js
Start Application
Listen port 7788
null
request method: POST
POST params should be next:
[object Object]
POST params: 1=bill&2=dave
So , it does appear to work. My question is now how to parse post body into variables, so I can access it in the rest of the script.

To read post data, you should not use request.headers as it's HTTP headers (encoding, cache, cookies, ...)
As said here, you should use request.post or request.postRaw.
request.post is a json object, so you write it into the console. That's why you get [object Object]. Try to apply a JSON.stringify(request.post) when logging.
As request.post is a json object, you can also directly read properties using indexers (do not forget to add a basic check if the property is not posted)
Here is an updated version of your script
// import the webserver module, and create a server
var server = require('webserver').create();
var port = require('system').env.PORT || 7788;
console.log("Start Application");
console.log("Listen port " + port);
// Create serever and listen port
server.listen(port, function (request, response) {
console.log("request method: ", request.method); // request.method POST or GET
if (request.method == 'POST') {
console.log("POST params should be next: ");
console.log(JSON.stringify(request.post));//dump
console.log(request.post['1']);//key is '1'
console.log(request.post['2']);//key is '2'
code = response.statusCode = 200;
response.write(code);
response.close();
}
});

Related

Code working on server give an error when running on localhost

To recreate code just simply follow this article
Final code is:
'use strict';
// Imports dependencies and set up http server
const
express = require('express'),
bodyParser = require('body-parser'),
app = express().use(bodyParser.json()); // creates express http server
// Sets server port and logs message on success
app.listen(process.env.PORT || 1337, () => console.log('webhook is listening'));
// Creates the endpoint for our webhook
app.post('/webhook', (req, res) => {
let body = req.body;
// Checks this is an event from a page subscription
if (body.object === 'page') {
// Iterates over each entry - there may be multiple if batched
body.entry.forEach(function(entry) {
// Gets the message. entry.messaging is an array, but
// will only ever contain one message, so we get index 0
let webhook_event = entry.messaging[0];
console.log(webhook_event);
});
// Returns a '200 OK' response to all requests
res.status(200).send('EVENT_RECEIVED');
} else {
// Returns a '404 Not Found' if event is not from a page subscription
res.sendStatus(404);
}
});
app.get('/webhook', (req, res) => {
// Your verify token. Should be a random string.
let VERIFY_TOKEN = "<YOUR_VERIFY_TOKEN>"
// Parse the query params
let mode = req.query['hub.mode'];
let token = req.query['hub.verify_token'];
let challenge = req.query['hub.challenge'];
// Checks if a token and mode is in the query string of the request
if (mode && token) {
// Checks the mode and token sent is correct
if (mode === 'subscribe' && token === VERIFY_TOKEN) {
// Responds with the challenge token from the request
console.log('WEBHOOK_VERIFIED');
res.status(200).send(challenge);
} else {
// Responds with '403 Forbidden' if verify tokens do not match
res.sendStatus(403);
}
}
});
Get request route is working fine but when I hit post with this request
curl -H "Content-Type: application/json" -X POST "localhost:1337/webhook" -d '{"object": "page", "entry": [{"messaging": [{"message": "TEST_MESSAGE"}]}]}'
I get this error despite a json is valid
SyntaxError: Unexpected token o in JSON at position 1
It's quite unexpected for me, this code works on server with same node version installed - 14.7.6

Connect node app and server + post image to server

I have a very basic question about a node application, and a question about HTTP requests. It's the first time I create a node app with server, and I just can't seem to get the different components to work together.
This is my server.js
var express = require('express');
var multer = require('multer');
const request = require('request');
const upload = multer({dest: __dirname + '/uploads/images'});
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.post('/upload', upload.single('photo'), (req, res) => {
if(req.file) {
res.json(req.file);
}
else throw 'error';
});
app.listen(PORT, () => {
console.log('Listening at ' + PORT );
});
Then I have a file app.js with a motion-detection system. Every time motion is detected, a picture is taken. This all works fine.
Then the picture should be sent to the server. This is what I can't figure out.
I created a function toServer() that should post the detected data to the server
const request = require('request');
function toServer(data) {
const formData = {
// Pass data via Buffers
my_buffer: data,
// Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS}
// Use case: for some types of streams, you'll need to provide "file"-related information manually.
// See the `form-data` README for more information about options: https://github.com/form-data/form-data
};
request.post({url:'http://localhost:3000/upload', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('Upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
};
Problem 1: when running the server.js on localhost:3000, it doesn't find any of the scripts loaded in index.html nor my app.js.
Problem 2: when running the index.html on live-server, all scripts are found, but i get the error "request is not defined".
I am pretty sure there is some basic node setup thing I'm missing.
The solution for toServer() might be more complicated.
Thanks for your time,
Mustard Shaper
Problem 1:
this could happen because you have not specified to render your index.html.
for example:
res.render('index')
if it's not because of the single quotes in upload.single('photo') try double quotes.
Another possible error could be that you are missing a default display engine setting.
an example: https://www.npmjs.com/package/hbs
Problem 2:
it may be because you are missing the header
var request = require('request');
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'http://localhost',
body: "example"
}, function(error, response, body){
console.log(body);
});
See more at https://expressjs.com/

Node JSON-Server returning MOCK post response

I'm trying to use https://www.npmjs.com/package/json-server as a mock backend, I'm able to match URLs for get, but how can i return some mock-response for POST calls.
Like for create user URL will be like
URL - http://localhost:4000/user
Method - POST
Request Data - {name:"abc", "address":"sample address"}
expected response -
httpStats Code - 200,
Response Data - {"message":"user-created", "user-id":"sample-user-id"}
In Some Cases I also want to send custom http codes like 500,423,404,401 etc.. depending upon some data.
Biggest problem is that my code is not returning anything response for POST, its only inserting records in JSON
By default POST requests through json-server should give a 201 created response.
If you need custom response handling, you might need a middleware to get hold of req and res object.
Here I'm adding a middleware to intercept POST requests and send a custom response. You could tweak it to your specific case.
// Custom middleware to access POST methods.
// Can be customized for other HTTP method as well.
server.use((req, res, next) => {
console.log("POST request listener");
const body = req.body;
console.log(body);
if (req.method === "POST") {
// If the method is a POST echo back the name from request body
res.json({ message:"User created successfully", name: req.body.name});
}else{
//Not a post request. Let db.json handle it
next();
}
});
Complete code (index.js)..
const jsonServer = require("json-server");
const server = jsonServer.create();
const router = jsonServer.router("db.json");
const middlewares = jsonServer.defaults();
server.use(jsonServer.bodyParser);
server.use(middlewares);
// Custom middleware to access POST methids.
// Can be customized for other HTTP method as well.
server.use((req, res, next) => {
console.log("POST request listener");
const body = req.body;
console.log(body);
if (req.method === "POST") {
// If the method is a POST echo back the name from request body
res.json({ message:"User created successfully", name: req.body.name});
}else{
//Not a post request. Let db.json handle it
next();
}
});
server.use(router);
server.listen(3000, () => {
console.log("JSON Server is running");
});
And you can start json-server using node index.js

D3.json Unexpected token with Node.js Server

trying to learn D3 I wrote the following local server:
const http = require('http');
const fs = require('fs');
function onRequest(request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('./index.html', null, function(error, data) {
if (error) {
response.writeHead(404);
// response.write('file not found');
} else {
response.write(data);
}
response.end();
});
}
http.createServer(onRequest).listen(8000, '127.0.0.1');
I then go to http://127.0.0.1:8000/ to render this index.html:
<html>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var stringit = `[{"coin_val": 4999999,"coin_lab": "#PAX"},{"coin_val": 1100000,"coin_lab": "#USDC"}]`;
console.log('working.')
d3.json('./data.json', function(err, data) {
console.log(err)
console.log(data)
});
</script>
</body>
</html>
but I receive the following error in Chrome console:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at
position 1
at Go (d3.v5.min.js:2) Go # d3.v5.min.js:2
What am I doing wrong? is it i the 3D code or I just don't get the server right? how can I get D3 to read a JSON file in a Node.js server?
I suspect the JSON is not the issue, something goes wrong on the server side and reads the HTML in a wrong way?
I wrote the following local server
Which serves up the contents of index.html in response to any request it gets.
d3.json('./data.json',
So your JavaScript asks for data.json and it gets the contents of index.html.
Since the contents of index.html are not JSON, and start with a <, it throws the error message. A JSON file cannot start with a <.
You need to fix your server so it gives the browser what it asks for instead of blindly sending index.html.
your problem seems to be that your code doesn't know how to serve anything but index.html. It is really frustrating working with a pure node server because most resources on the internet assume that users are going to employ express or another framework.
Below I have a server that can serve static websites and handle requests for a few common types of media. You can add other types by modifying the code in the getContentType function by looking up the mime type for that file format.
I hope this helps
'use strict'
// Step 1: Declare Constants and Require External Resources
const port = "8888", landing = 'index.html', hostname = "127.0.0.1";
const path = require('path');
const http = require('http');
const fs = require('fs');
const qs = require('querystring');
// Step 2: Create getContentType Function that Returns the Requested MimeType for the browser
/**
* getContentType :: str -> str
*
* Function returns the content type that matches the resource being
* requested by the server controller
*/
function getContentType(url){
const mimeTypes = {
'.html' : 'text/html' , '.js' : 'text/javascript' ,
'.css' : 'text/css' , '.json' : 'application/json' ,
'.png' : 'image/png' , '.jpg' : 'image/jpg' ,
'.gif' : 'image/gif' , '.svg' : 'image/svg+xml' ,
'.wav' : 'audio/wav' , '.mp4' : 'video/mp4' ,
'.woff' : 'application/font-woff' , '.ttf' : 'application/font-ttf' ,
'.otf' : 'application/font-otf' , '.eot' : 'application/vnd.ms-fontobject' ,
'.wasm' : 'application/wasm'
};
// If requested url extension is a mime type, the dict object will return that url's value,
// otherwise octet-stream will be returned instead
return mimeTypes[path.extname(url).toLowerCase()] || 'application/octet-stream';
}
// Step 3: Create sendFile Function that Delivers Requested files to the Response stream
/**
* sendFile :: (str, str, str, stream) -> void
*
* function delivers any requested resources to the stream
*/
function sendFile(file, url, contentType, request, response){
fs.readFile(file, (error, content) => {
if(error) {
response.writeHead(404)
.write(`404 Error: '${url}' Was Not Found!`);
response.end();
// include file path for easy debugging, tabs added to make distinct
console.log(`\t${request.method} Response: 404 Error, '${file}' Was Not Found!`);
} else {
response.writeHead(200, {'Content-Type': contentType})
.write(content);
response.end();
console.log(`\t${request.method} Response: 200, ${url} Served`);
};
});
};
// Step 4: Create serverController Function to initialize the server and run the request loop
/**
* serverController :: str -> void
*
* Function creates a server and accesses sendFile and getContentType to serve
* requested resources
*/
function serverController(hostname) {
const server = http.createServer((request, response) => {
// Creates space around .html requests so that they stand out more in the console
if (path.extname(request.url) == '.html' || request.url == '/') {
console.log(`\nPage Requested: ${request.url}\n`);
} else {
if (request.method == "GET") {
console.log(`${request.method} Request: ${request.url}`);
} else {
console.log(`Request came: ${request.url}`);
}
}
// Sends the requested resources to the response stream
if (request.url == '/') {
var file = path.join(__dirname, landing); // delivers index.html by default
sendFile(file, landing, 'text/html', request, response);
} else {
var file = path.join(__dirname, request.url); // delivers requested resource
sendFile(file, request.url, getContentType(request.url), request, response);
};
});
// Gives server a port to listen to and gives an IP address to find it
server.listen(port, hostname, () => {
console.log(`Server running at ${hostname}:${port}\n`);
});
}
// Step 6: Create launch IIFE Function that Starts the server upon Instantiation
(function launch() {
serverController(hostname);
})();

Wait for socketio event inside express route

I'm using express,socketio and socketio-client in my application.
(I not very comfortable with nodejs stack...)
to summarize my application flow :
Client => node/express API + Socketoi server <=> nodejs (Socketio-client)
browser send request to a nodejs/express (route /api)
Do some request headers overwrites with middlewares
In the route '/', server sends an emit to a nodejs (Socketio-client)
after executing some logic, socketio-client emit an event with the logics result
I need this result to be send in the response to the client
My code below:
router.get('/*', function (req, res) {
//emit data for socketio-client to apply some logic
app.io.sockets.emit('req', {
reqheader : req.headers,
requrl : req.protocol + "://" + req.headers.host + req.url,
reqmethod : req.method
});
console.log("after emit");
//I use callback to make response wait for socketio server to catch event from client
waitforevent(req, res, function (__res) {
console.log("callback" );
res.end(__res.body);
res.sendStatus(__res.statusCode);
//res.end();
});
function waitforevent(req, res, callback) {
console.log("waiting for event" );
app.io.__socket.on('respp', function (data) {
//console.log("no response yet \n" + JSON.parse(data) );
__res = JSON.parse(data);
console.log("event catched...");
callback(__res);
});
}
});
My problem :
This works only the first time I send a Get http://localhost:3000/api frome the browser. __res.body is printed in the browser.
req 1
after emit
waiting for event
event catched...
callback
Error: Can't set headers after they are sent.
**GET /api 200 73.841 ms - -**
req 2
after emit
waiting for event
Next request will just wait for server to respond, which is, I suspect, not happening because the app.io.__socket.on('respp', function (data){...} is never catched by the server.
After sending more request (while the others are waiting), I noticed this warning in server logs:
(node) warning: possible EventEmitter memory leak detected. 11 respp listeners added. Use emitter.setMaxListeners() to increase limit.
Is there other ways to catch events in a route before sending response to clients?
I solved with once:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var socket;
io.on('connection', function (sock) {
console.log('Connected');
socket = sock;
});
server.listen(3000);
app.get('/*', function (req, res) {
socket.once('event', function (data) {
if (data.error) {
console.log('is an error');
res.status(400).json(data);
} else {
console.log('is ok');
res.status(200).json(data);
}
});
io.emit('ask-for-event', { data: data });
});
You could remove the event listener when the socket closes to avoid the event listener leak:
router.get('/*', function (req, res) {
app.io.sockets.emit('req', {
reqheader : req.headers,
requrl : req.protocol + "://" + req.headers.host + req.url,
reqmethod : req.method
});
req.socket.on('close', function() {
app.io.__socket.removeListener('respp', resppHandler);
});
app.io.__socket.on('respp', resppHandler);
function resppHandler(data) {
data = JSON.parse(data);
res.statusCode = data.statusCode;
res.end(data.body);
}
});
I'm not sure if app.io.__socket should really be app.io.sockets or not, but I copied it as-is from your code, assuming you know what you're doing.
Additionally, you may wish to add some sort of timeout so as not to keep the request waiting indefinitely.

Categories

Resources