How to post JSON data to another server by lambda script - php

I am trying to send some JSON data(Fetched From DaynamoDB) to another server from AWS lambda function but while giving the URL in the script :
'use strict';
const https = require('https');
exports.handler = (event, context, callback) => {
var options = {
hostname: 'https://www.corecomputersystem.com',
path: '/getSyncData.php',
port : 432,
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
event.Records.forEach((record) => {
console.log(record.eventID);
console.log(record.eventName);
console.log('DynamoDB Record: %j', record.dynamodb);
var res = record.dynamodb;
const req = https.request(options, (res) => {
let body = "";
console.log('Status:', res.statusCode);
console.log('Headers:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
console.log('Successfully processed HTTPS response');
// If we know it's JSON, parse it
if (res.headers['content-type'] === 'application/json') {
body = JSON.parse(body);
}
callback(null, body);
});
});
req.on('error', callback);
req.write(JSON.stringify(event.data) + "");
req.end();
//context.succeed();
});
};
it's throwing following error,
{
"errorMessage": "getaddrinfo ENOTFOUND https://www.corecomputersystem.com https://www.corecomputersystem.com:432",
"errorType": "Error",
"stackTrace": [
"errnoException (dns.js:26:10)",
"GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:77:26)"
]
}
and if I uncomment the context.succeed(), there is no error, I need help for identifying the error.

Just for deeply with #at0mzk says, a hostname never take any port number, so any prefix like [http, https, smb, nfs]:// will throw an error any where a hostname is requested.
(http://localhost === localhost:80)

remove https:// from hostname variable.
var options = {
hostname: 'www.corecomputersystem.com',
path: '/getSyncData.php',
port : 432,
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
see docs.

Before making HTTPS request we can use :
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
so it will not ask for authorization.

Another way we can add a key in option before requesting HTTP:
rejectUnauthorized: false
It will not ask for self asigned certificate.
This is what I was searching for.

This worked for me.
In lambda use the following node js.
const https = require('https');
var querystring = require("querystring");
const doPostRequest = (event) => {
//parameters to post
const params = {
name: "John",
title: "Developer",
userid: 123
};
var qs = querystring.stringify(params);
var qslength = qs.length;
return new Promise((resolve, reject) => {
const options = {
host: 'example.com',//without https or http
path: '/yourpath/yourfile.php',
method: 'POST',
port: 443, // replace with 80 for HTTP requests
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': qslength
}
};
var buffer = "";
//create the request object with the callback with the result
const req = https.request(options, (res) => {
resolve(JSON.stringify(res.statusCode));
res.on('data', function (chunk) {
buffer+=chunk;
});
res.on('end', function() {
console.log(buffer);
});
});
// handle the possible errors
req.on('error', (e) => {
reject(e.message);
});
//do the request
req.write(qs);
//finish the request
req.end();
});
};
exports.handler = async (event) => {
try {
const result = await doPostRequest(event);
console.log('result is:️ ', result);
//️️ response structure assume you use proxy integration with API gateway
return {
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(result),
};
} catch (error) {
console.log('Error is:️ ', error);
return {
statusCode: 400,
body: error.message,
};
}
};
For some reason lambda didnt show the response for me other than 200. So I had to create a logfile on my server to verify that it was sending the POST values. From there you can use json_encode to show the posted string or just echo the POST values
$inputJSON = json_encode($_POST);
$input = json_decode($inputJSON, TRUE);
$log = "Data: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
"Data: ".$inputJSON.PHP_EOL.
"Data: ".$input.PHP_EOL.
"Data: ".$_POST['name'].PHP_EOL.
"Data: ".$_POST['title'].PHP_EOL.
"Data: ".$_POST['userid'].PHP_EOL.
"-------------------------".PHP_EOL;
//Save string to log, use FILE_APPEND to append.
file_put_contents('./log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

Related

ElephantIO not sending to clinet and always showing user disconnected

I am sending data from clinet.php file and can not get data in client.js and always showing user disconnected. What can be reason?
clinet.php
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X;
$client = new Client(new Version2X('http://localhost:9009', [
'headers' => [
'X-My-Header: websocket rocks',
'Authorization: Bearer 12b3c4d5e6f7g8h9i'
]
]));
$client->initialize();
$client->emit('user', ['foo' => 'bar']);
$client->close();
server.js
const server = require('http').createServer();
const io = require("socket.io")(server);
io.on('connection', function (socket) {
socket.on('listen', function (data) {
console.log('client connected');
io.emit('user', {name: 'Marcelo Aires'});
});
// If some user disconnect
socket.on('disconnect', function () {
console.log('user disconnected');
})
});
server.listen(9009);
client.js
var socket = io('http://localhost:9009');
socket.on('user', function (data) {
console.log(data);
});

Ionic 3 post image using form-data

I'm trying to post form data, consists of text and image file to PHP server.
I use ionic native camera to get a picture from gallery:
const options: CameraOptions = {
quality: 70,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
saveToPhotoAlbum:false,
targetWidth: 400,
targetHeight: 400
}
this.camera.getPicture(options).then((imageData) => {
this.myphoto = normalizeURL(imageData);
this.myphoto2 = imageData;
}, (err) => {
});
And post it using form data:
var headers = new Headers();
headers.append('Content-Type', 'multipart/form-data;boundary=' + Math.random());
headers.append('Accept', 'application/json');
let options = new RequestOptions({
headers: headers
});
let formData = new FormData();
formData.append('judul', this.judul.value);
formData.append('photo', this.myphoto, '123.jpg');
this.http.post('http://localhost/upload.php', formData, options)
.map(...)
.subscribe(...);
But, I saw on PHP log, the form-data not sent by ionic.
What's wrong here?
You can try removing 'options' from the this.http.post() arguments.
Your code becomes :
this.http.post('http://localhost/upload.php', formData)
.map(...)
.subscribe(...);
If this doesn't work,
try sending across the entire BASE64 Image using
'destinationType: this.camera.DestinationType.DATA_URL'
i advise you use the native plugin to upload file :
https://ionicframework.com/docs/native/file-transfer/
First Take Photo From Camera
async takePhoto() {
const options: CameraOptions = {
quality: 70,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
saveToPhotoAlbum:false,
targetWidth: 400,
targetHeight: 400
}
this.camera.getPicture(options).then((imageData) => {
this.getSystemURL(imageData);
}, (err) => {
});
}
Than Get a Local System Image URL
private getSystemURL(imageFileUri: any): void {
this.file.resolveLocalFilesystemUrl(imageFileUri)
.then(entry => (entry as FileEntry).file(file => {
this.readFile(file);
}))
.catch(err => console.log(err));
}
After Read That Image URL
private readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
this.myphoto = new Blob([reader.result], {type: file.type});
var headers = new Headers();
headers.append('Content-Type', 'multipart/form-data;boundary=' + Math.random());
headers.append('Accept', 'application/json');
let options = new RequestOptions({
headers: headers
});
let formData = new FormData();
formData.append('judul', this.judul.value);
formData.append('photo', this.myphoto, '123.jpg');
this.http.post('http://localhost/upload.php', formData, options)
.map(...)
.subscribe(...);
};
reader.readAsArrayBuffer(file);
}
It is working for me,
Hope it will help.

Request header field Access-Control-Allow-Origin is not allowed in AnguarJS calls for PHP APIs

I am using AngularJS to call php APIs but I have the following problem:
XMLHttpRequest cannot load
http://www.example.com/api/v1/getCategories.php. Response to preflight
request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://example.com' is therefore not allowed access.
AngularJs code:
app.factory("Data", ['$http', 'toaster',
function ($http, toaster) { // This service connects to our REST API
var serviceBase = 'http://www.example.com/api/v1/';
var conf= {headers: {
'Access-Control-Allow-Origin':'http://example.com',
'Content-Type': 'application/json'
}
};
var obj = {};
obj.toast = function (data) {
toaster.pop(data.status, "", data.message, 10000, 'trustedHtml');
}
obj.get = function (q) {
return $http.get(serviceBase + q,conf).then(function (results) {
return results.data;
});
};
obj.post = function (q, object) {
return $http.post(serviceBase + q, object, conf).then(function (results) {
return results.data;
});
};
obj.put = function (q, object) {
return $http.put(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.delete = function (q) {
return $http.delete(serviceBase + q).then(function (results) {
return results.data;
});
};
return obj;
}]);
Can you please help me to figure out what is the problem ?

How to Sync PHP and NodeJS with Redis and get data in order

I have a example code for make experiments trying to think "how to ""sync"" nodejs and php in a simple chat example.
Here is my NodeJS server:
var redis = require('redis'),
subscriber = redis.createClient(),
publisher = redis.createClient();
//var sckio = require('socket.io').listen(8888);
var http = require('http');
var querystring = require('querystring');
var WebSocketServer = require('ws').Server
var ENCODING = 'utf8';
var tCounter = 0;
/* #################################### */
// Event on "subscribe" to any channel
subscriber.on("subscribe", function (channel, count) {
// Publish to redis server Test Message
publisher.publish("chat", "NODEJS MESSAGE");
});
// Suscrib to redis server
subscriber.on('message', function (channel, json) {
console.log('SUB: ' + channel + ' | ' + json);
console.log('PHP PUSH TO REDIS, AND NODE CAPTURE REDIS PUSH: ' + (getMicrotime(true) - tCounter));
});
subscriber.subscribe('chat'); // Subs to "mysql" channel
/*
var clients = [];
sckio.sockets.on('connection', function (socket) {
clients.push(socket);
publisher.publish("chat", "User connected");
socket.on('message', function (from, msg) {
publisher.publish("chat", msg);
clients.forEach(function (client) {
if (client === socket) return;
client.send(msg);
});
});
socket.on('disconnect', function () {
clients.splice(clients.indexOf(socket), 1);
publisher.publish("chat", "User disconnected");
});
});
*/
var wss = new WebSocketServer({port: 8888, timeout : 500});
var wsClients = [];
wss.on('connection', function(ws) {
ws.AUTH_ID = Math.random();
wsClients.push(ws);
publisher.publish("chat", "User enter");
ws.on('message', function(message) {
wsClients.forEach(function (client) {
client.send(ws.AUTH_ID + ' ' + message);
});
tCounter = getMicrotime(true);
console.log('CALL TO PHP: ' + tCounter);
PostCode('CODE TO PHP FROM NODE', function() {
wsClients.forEach(function (client) {
client.send('PHP SAVE DATA');
});
});
});
ws.on('close', function(message) {
wsClients.splice(wsClients.indexOf(ws), 1);
publisher.publish("chat", "User left");
});
ws.send('HELLO USER!');
});
function getMicrotime(get_as_float) {
var now = new Date().getTime() / 1000;
var s = parseInt(now, 10);
return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
}
function PostCode(codestring, callback) {
// Build the post string from an object
var post_data = querystring.stringify({
'output_format': 'json',
'js_code' : codestring
});
// An object of options to indicate where to post to
var post_options = {
host: '127.0.0.1',
port: '80',
path: '/NodeJS/chat_system/php_system.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length
}
};
// Set up the request
var post_req = http.request(post_options, function(res) {
res.setEncoding(ENCODING);
res.on('data', function (chunk) {
console.log('Response FROM PHP: ' + chunk);
if (typeof callback == 'function') {
callback(chunk);
}
});
});
// post the data
post_req.write(post_data);
post_req.end();
}
Here is my PHP Server
require 'Predis/Autoloader.php';
Predis\Autoloader::register();
function pushToRedis($data) {
try {
$redis = new Predis\Client(array(
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
));
} catch (Exception $e) {
echo "Couldn't connected to Redis";
echo $e->getMessage();
return false;
}
$json = json_encode($data);
$redis->publish("chat", $json);
return true;
}
pushToRedis('PHP PUSH TO REDIS!');
header('Content-Type: application/json');
echo json_encode(array('response' => print_r(array($_REQUEST, $_SERVER), true)));
And my client:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSockets - Simple chat</title>
<style>
.chat { width: 400px; height: 250px; overflow-y: scroll; }
</style>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var connection = new WebSocket('ws://127.0.0.1:8888');
$(document).ready(function() {
/*
var socket = io.connect('http://127.0.0.1:8888');
socket.on('message', function (data) {
alert(data);
});
socket.send('HELLO!');
*/
connection.onopen = function () {
console.log('connected!');
};
connection.onerror = function (error) {
};
connection.onmessage = function (message) {
$('.chat').append(message.data + '<br>');
$('.chat').scrollTop($('.chat')[0].scrollHeight);
};
$('input[name="text"]').on('keydown', function(e) {
if (e.keyCode === 13) {
var msg = $(this).val();
connection.send(msg);
$(this).val('').focus();
}
});
});
</script>
<div class="chat">
</div>
<input type="text" name="text">
</body>
</html>
The problem is the order of the PHP return the response to NodeJS via Redis when the network its bussy.
For example: I send more messages from de javascript client, then, NodeJS call to PHP every message, PHP save the data in MYSQL, and call Redis, NodeJS detect the Redis push and update the clients. But, in some cases, if i send from the Javascript client in loop some messages ( for(0-10000)) I dont reply to others clients in the same order, in cases geting numbers like 200,201,300,202,320,203 in the clients.
I think this is for the PHP delay to response.
My question is How i can manage the responses to update the clients, in the correct order? because this problem can cause, to clients receive the chat messages in wrong order.
But why you want to use php you able to send data to mysql directly using mysql package of nodejs
You may install mysql package via :
npm install mysql
Connection made by :
mysql = require('mysql'),
connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'password',
database: 'database name',
port: 3306
}),
And throw query by using :
var q=connection.query('select * from table);

Node.js server sends back EOF block the PHP server

I have a node.js server opening 8000 port. It is a chat server.
I have another PHP server and I use proxy + virtual host so when I go www.phpserver.com/chat It proxies to the node.js server. I did this so I can use ajax to call the node.js server.
Right now, everything works fine when i run the node.js server, however, after a while (a random time frame, not necessarily long or short), the PHP server will crush because it gets an EOF from the node.js server and it's just stuck there until I stop/restart the node.js server.
The error I get is(from php error log):
(70014)End of file found: proxy: error reading status line from remote
server nodeserver.com:8000, referer: https://www.phpserver.com
I asked some professionals and they said it's because of the PHP server sends the request to the node.js server successfully and receives an EOF or fails to receive any response. I don't understand how to fix it tho. What should I do so even the node.js server crushes, it won't crush the PHP server? Should I get rid of the proxy+ajax and starts to use socket.io?
Please advise.
Thank you!
Below is some node codes.
From middleware:
this.events.addListener('update', o_.bind(function(package) {
if(this.clear != 0){
delete this.sessions[this.clear];
}
var _package = package.toJSON();
if(package.type == 'status' && package.status == 'offline') {
var sids = Object.keys(this.sessions), sid, sess;
for(sid in this.sessions) {
sess = this.sessions[sid];
if(sess.data('username') == package.username) {
if(sess.listeners.length)
sess.send(200, {type: 'goodbye'});
delete this.sessions[sid];
break;
}
}
}
}, this));
};
Hub.prototype.destroy = function(sid, fn) {
this.set(sid, null, fn);
};
Hub.prototype.reap = function(ms) {
var threshold = +new Date - ms,
sids = Object.keys(this.sessions);
for(var i = 0, len = sids.length; i < len; ++i) {
var sid = sids[i], sess = this.sessions[sid];
if(sess.lastAccess < threshold) {
this.events.emit('update', new packages.Offline(sess.data('username')));
}
}
};
Hub.prototype.get = function(req, fn) {
if(this.sessions[req.sessionID]) {
fn(null, this.sessions[req.sessionID]);
} else {
this.auth.authenticate(req, o_.bind(function(data) {
if(data) {
var session = new User(req.sessionID, data);
this.set(req.sessionID, session);
this.auth.friends(req, data, o_.bind(function(friends) {
var friends_copy = friends.slice();
o_.values(this.sessions).filter(function(friend) {
return ~friends.indexOf(friend.data('username'));
}).forEach(function(friend) {
var username = friend.data('username');
friends_copy[friends_copy.indexOf(username)] =
[username, friend.status()];
}, this);
session._friends(friends_copy);
console.log("refreshed");
session.events.addListener('status',
o_.bind(function(value, message) {
this.events.emit(
'update',
new packages.Status(session.data('username'),
value,
message)
);
}, this));
this.events.addListener('update',
o_.bind(session.receivedUpdate, session));
this.set(req.sessionID, session);
fn(null, session);
}, this));
} else {
fn();
}
}, this));
}
};
From app.js
#!/usr/bin/env node
var sys = require('sys'),
express = require('express'),
packages = require('./libs/packages'),
fs = require('fs'),
o_ = require('./libs/utils'),
https = require('https');
o_.merge(global, require('./settings'));
try { o_.merge(global, require('./settings.local')); } catch(e) {}
try {
var daemon = require('./libs/daemon/daemon'),
start = function() {
daemon.init({
lock: PID_FILE,
stdin: '/dev/null',
stdout: LOG_FILE,
stderr: LOG_FILE,
umask: 0,
chroot: null,
chdir: '.'
});
},
stop = function() {
process.kill(parseInt(require('fs').readFileSync(PID_FILE)));
};
switch(process.argv[2]) {
case 'stop':
stop();
process.exit(0);
break;
case 'start':
if(process.argv[3])
process.env.EXPRESS_ENV = process.argv[3];
start();
break;
case 'restart':
stop();
start();
process.exit(0);
break;
case 'help':
sys.puts('Usage: node app.js [start|stop|restart]');
process.exit(0);
break;
}
} catch(e) {
sys.puts('Daemon library not found! Please compile ' +
'./libs/daemon/daemon.node if you would like to use it.');
}
var options = {
key: fs.readFileSync('/home/ec2-user/key.pem'),
cert: fs.readFileSync('/home/ec2-user/cert.pem'),
ca: fs.readFileSync('/home/ec2-user/ca.pem'),
};
var app = express();
//app.set('env', 'development');
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(require('./middleware/im')({
maxAge: 30 * 1000,
reapInterval: 20 * 1000,
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
}));
app.set('root', __dirname);
if ('development' == app.get('env')) {
app.set('view engine', 'jade');
app.set('views', __dirname + '/dev/views');
app.stack.unshift({
route: '/dev',
handle: function(req, res, next) {
req.dev = true;
next();
}
});
app.use(express.logger());
require('./dev/app')('/dev', app);
app.use(express.static(
require('path').join(__dirname, '../client')));
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
}
//app.listen(APP_PORT, APP_HOST);
// Listener endpoint; handled in middleware
app.get('/listen', function(){});
app.post('/message', function(req, res) {
res.find(req.body['to'], function(user) {
if(!user)
return res.send(new packages.Error('not online'));
res.message(user, new packages.Message(
req.session.data('username'),
req.body.body
));
});
});
app.post('/message/typing', function(req, res) {
if(~packages.TYPING_STATES.indexOf('typing' + req.body['state'])) {
res.find(req.body['to'], function(user) {
if(user) {
res.message(user, new packages.Status(
req.session.data('username'),
'typing' + req.body.state
));
}
// Typing updates do not receive confirmations,
// as they are not important enough.
res.send('');
});
} else {
res.send(new packages.Error('invalid state'));
}
});
app.post('/status', function(req, res) {
if(~packages.STATUSES.indexOf(req.body['status'])) {
res.status(req.body.status, req.body.message);
res.send(new packages.Success('status updated'));
} else {
res.send(new packages.Error('invalid status'));
}
});
app.post('/online', function(req, res) {
var d = new Date();
var n = d.getTime() + 30;
req.sessionID.expires = n;
res.status(req.body.status, 'available');
});
app.post('/signoff', function(req, res) {
res.signOff();
res.send(new packages.Success('goodbye'));
});
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Error on the node/express server.');
});
https.createServer(options, app).listen(8000);
I can't help you answer your question but I can try to point you in a right direction.
I'm currently working on a Node JS server myself, and I found very useful to have a logger setup.
There are a few of them, but my favorite is Winston so far.
Reference: https://github.com/flatiron/winston
To install Winston for your Node JS server (seems you have already installed a few modules):
npm install winston
Then I have logger module setup as (logger.js):
/**
* Usage:
* - logger.info('sample text');
* - logger.warn('sample text');
* - logger.error('sample text');
*/
// Load modules
var winston = require('winston');
// Create custom logger
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ json: false, timestamp: true }),
new winston.transports.File({ filename: __dirname + '/debug.log', json: false })
],
exceptionHandlers: [
new (winston.transports.Console)({ json: false, timestamp: true }),
new winston.transports.File({ filename: __dirname + '/exceptions.log', json: false })
],
exitOnError: false
});
// Export logger
module.exports = logger;
Finally I load in Winston logger module into my server scripts by:
var logger = require('./logger');
It will automatically log any exceptions into exceptions.log on your Node JS server location. It helped me out a lot to catch exceptions I haven't noticed before within Node JS unrelated to PHP.
P.S. Also check out socket.io, that may simplify what you are trying to do.

Categories