I'm currently going through Guillermo Rauchs "Smashing Node.Js" Book. I'm stuck in chapter 7 where the task is to set up a client/server and to send a string from the client to the server over a http connection. The string should be printed from the server.
the client code:
var http = require('http'), qs = require('querystring');
function send (theName) {
http.request({
host: '127.0.0.1'
, port: 3000
, url: '/'
, method: 'GET'
}, function (res) {
res.setEncoding('utf-8');
res.on('end', function () {
console.log('\n \033[090m request complete!\033[39m');
process.stdout.write('\n your name: ');
})
}).end(qs.stringify({ name: theName}));
}
process.stdout.write('\n your name: ');
process.stdin.resume();
process.stdin.setEncoding('utf-8');
process.stdin.on('data', function (name) {
send(name.replace('\n', ''));
});
the server:
var http = require('http');
var qs = require('querystring');
http.createServer(function (req, res) {
var body = '';
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
res.writeHead(200);
res.end('Done');
console.log('\n got name \033[90m' + qs.parse(body).name + '\033[39m\n');
});
}).listen(3000);
I start the client and the server. The client seems to work:
mles#se31:~/nodejs/tweet-client$ node client.js
your name: mles
request complete!
your name:
However on the server side, it's only showing an undefined:
mles#se31:~/nodejs/tweet-client$ node server.js
got name undefined
According to the book, here should be an "mles" too.
, method: 'GET'
should be
, method: 'POST'
GET requests do not have a body so there is nothing to parse on the server's side.
Related
I start learning Node.js and Express.js and I'm trying to create a simple API to list data from JSON file (using the GET method) and add a new user using the POST method.
the GET method works fine but the POST method does not work
when I request http://127.0.0.1:8080/listusers the API sends all users in a JSON file.
when I request http://127.0.0.1:8080/adduser the API has to add new User Info and send the new data back to the browser.
NOTE: I read all the questions on Stackoverflow about this problem but
non of them help me so I have to ask again.
the problem is when I request http://127.0.0.1:8080/adduser I get the following error
Cannot GET /adduser
here is the server.js:
var express = require('express');
var app = express();
var fs = require('fs');
var user = {
"user4" : {
"name" : "mounir",
"password" : "password4",
"profession" : "teacher",
"id": 4
}
};
app.post('/adduser', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
data["user4"] = user["user4"];
console.log( data );
res.end(JSON.stringify(data) );
});
});
app.get('/listusers', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
console.log(data);
res.end(data);
});
});
var server = app.listen(8080, function () {
var host = server.address().address;
var port = server.address().port;
console.log("listening at http://%s:%s", "0.0.0.0", port)
});
The answer is in the error. Cannot GET /adduser. Keyword GET! If you are making a post request, be sure you include the appropriate headers and that you are making a POST request, with a body, and not a GET request. For instance if you are using fetch:
const myInit = {
method: 'POST',
headers: myHeaders,
body: {
...
}
};
fetch("http://127.0.0.1:8080/adduser", myInit)
.then(res => {
...
});
I'm just starting to learn Node.js and right now, I'm trying to use a Node.js Application through cPanel to provide a JSON response when its app's URL is accessed.
When visiting the app's URL, it's evident that the Node.js server is working as it should. So after editing the main JS file, and restarting the Node.js app, changes are reflected when visiting the URL again.
My problem:
Within the function of https.createServer( function (req, res) {});, I want to make an HTTPS request to a PHP file elsewhere, which returns a JSON response. At the moment, I can't even get a response or error from any type of request with the PHP file.
var https = require('https');
var server = https.createServer(function (req, res) {
var message = "";
res.writeHead(200, {
'Content-Type': 'text/plain'
});
var options = {
host: "mydomain.com",
path: '/myPhpScript.php'
};
https.get(options, function(res) {
var bodyChunks = [];
res.on('data', function(chunk) {
bodyChunks.push(chunk);
}).on('end', function() {
var body = Buffer.concat(bodyChunks);
message += body;
})
}).on('error', function(e) {
message += e;
});
res.end(message);
});
server.listen();
As you can see, message would be what's displayed to the browser window, but it's empty. Nothing appears when visiting the App URL. Is it possible to make an HTTPS request with a Node.js HTTPS server?
Note:
I've also tried with native-request and axios and have experienced the same issue.
Server code:
var http = require('http');
var https = require("https");
var server = http.createServer(function (req, res) {
let call = new Promise((resolve, reject) => {
var options = {
host: "jarrenmorris.com",
port: 443,
path: '/gamesense/r6_db/1.json'
};
https.get(options, function (res) {
var bodyChunks = [];
res.on('data', function (chunk) {
bodyChunks.push(chunk);
}).on('end', function () {
resolve(Buffer.concat(bodyChunks));
});
}).on('error', function (e) {
reject(e);
});
});
call.then((data) => {
// do something here with the successful request/json
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end(data);
}).catch((err) => {
// do something here with the failure request/json
// res.write("ERROR:");
res.end(err);
});
});
server.listen(8081, "127.0.0.1", () => {
console.log(`Server listen on ${server.address().address}:${server.address().port} `);
});
Response:
{"name":"tim","age":"42"}
First thing i noticed, while i tried to run your code was, you cant establish a connection to your node.js.
The reason for this was you use the https module, but didnt specify an certificates/keyfiles. Skip this, and work with http till you get the result you want.
Then i wrapped you https request to the external api/file in a promise.
This allows a simple chaining and better readability of the code.
When the promises resolves/fullfill, we answer the request on the http server with the data we received from the external request.
The res.end in your code (where you put it) made no sense, since you didnt wait for the external request to complete. Thats the reason why its nothing is shown in the browser window.
Currently I'm using the below code to connect with web service.
I need to connect to the Microsoft Azure Machine Learning Studio Api by using either Vue Axios or Express. Can someone help me.
var http = require("http");
var https = require("https");
var querystring = require("querystring");
var fs = require('fs');
function getPred(data) {
console.log('===getPred()===');
var dataString = JSON.stringify(data)
var host = 'ussouthcentral.services.azureml.net'
var path = '/workspaces/fda91d2e52b74ee2ae68b1aac4dba8b9/services/1b2f5e6f99574756a8fde751def19a0a/execute?api-version=2.0&details=true'
var method = 'POST'
var api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=='
var headers = {'Content-Type':'application/json', 'Authorization':'Bearer ' + api_key};
var options = {
host: host,
port: 443,
path: path,
method: 'POST',
headers: headers
};
console.log('data: ' + data);
console.log('method: ' + method);
console.log('api_key: ' + api_key);
console.log('headers: ' + headers);
console.log('options: ' + options);
var reqPost = https.request(options, function (res) {
console.log('===reqPost()===');
console.log('StatusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', function(d) {
process.stdout.write(d);
});
});
// Would need more parsing out of prediction from the result
reqPost.write(dataString);
reqPost.end();
reqPost.on('error', function(e){
console.error(e);
});
}
//Could build feature inputs from web form or RDMS. This is the new data that needs to be passed to the web service.
function buildFeatureInput(){
console.log('===performRequest()===');
var data = {
"Inputs": {
"input1": {
"ColumnNames": ["gl10", "roc20", "uo", "ppo", "ppos", "macd", "macds", "sstok", "sstod", "pmo", "pmos", "wmpr"],
"Values": [ [ "0", "-1.3351", "50.2268", "-0.2693", "-0.2831", "-5.5310", "-5.8120", "61.9220", "45.3998", "-0.0653", "-0.0659", "-30.3005" ], ]
},
},
"GlobalParameters": {}
}
getPred(data);
}
function send404Reponse(response) {
response.writeHead(404, {"Context-Type": "text/plain"});
response.write("Error 404: Page not Found!");
response.end();
}
function onRequest(request, response) {
if(request.method == 'GET' && request.url == '/' ){
response.writeHead(200, {"Context-Type": "text/plain"});
fs.createReadStream("./index.html").pipe(response);
}else {
send404Reponse(response);
}
}
http.createServer(onRequest).listen(8050);
console.log("Server is now running on port 8050");
buildFeatureInput();
But can i do this by using axios call or express server.
can anyone help me with proper syntax if i can do this using either vue axios or express server.
It sounds like you want to use express in server with axios in Vue front page instead of Node http server with https client in server-side.
To replace Node http with express is very easy, it is as below.
const express = require('express')
const path = require('path');
const app = express()
const port = 8050
app.use(express.static(path.join(__dirname, '.')))
app.get('/', (req, res) => res.sendFile('index.html'))
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err)
})
app.use(function (err, req, res, next) {
if(err.status == 404) {
res.status(404).send("Error 404: Page not Found!")
}
res.status(500).send("Error 500: Internal Error!")
})
app.listen(port, () => console.log("Server is now running on port 8050"))
But consider for the security of the api-key value for calling Azure Machine Learning Studio API, I recommended not to call the API with axios in Vue front page and still make the calling works in the server-side by express, as below.
const axios = require('axios');
var host = 'ussouthcentral.services.azureml.net'
var path = '/workspaces/fda91d2e52b74ee2ae68b1aac4dba8b9/services/1b2f5e6f99574756a8fde751def19a0a/execute?api-version=2.0&details=true'
var api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=='
const pred = axios.create({
baseURL: 'https://'+host,
timeout: 1000,
headers: {'Content-Type':'application/json', 'Authorization':'Bearer ' + api_key}
});
app.post('/mls-api', (req, res) => pred.post(path, JSON.stringify(req.body)).then(function(resp) {
resp.pipe(res)
}))
Then, you can call /mls-api url from Vue front page with the data value below.
var data = {
"Inputs": {
"input1": {
"ColumnNames": ["gl10", "roc20", "uo", "ppo", "ppos", "macd", "macds", "sstok", "sstod", "pmo", "pmos", "wmpr"],
"Values": [ [ "0", "-1.3351", "50.2268", "-0.2693", "-0.2831", "-5.5310", "-5.8120", "61.9220", "45.3998", "-0.0653", "-0.0659", "-30.3005" ], ]
},
},
"GlobalParameters": {}
}
axios.post('/mls-api', data)
.then(function (response) {
console.log(response);
})
I try send the values to my server, but If I try, my console show me the error:
Cannot POST /
I try see other examples, and I try with this codes:
My index.html:
function sendData() {
var latestResponse = Api.getResponsePayload();
var context = latestResponse.context;
var mail = context.email; // I can see the data of these variables perfectly on the console
$.ajax({
type: "POST",
url: "http://localhost:3000/",
crossDomain:true,
dataType: "json",
data:JSON.stringify({email: mail})
}).done(function ( data ) {
alert("ajax callback response:"+JSON.stringify(data));
})
}
My server.js:
'use strict';
var server = require('./app');
var port = process.env.PORT || process.env.VCAP_APP_PORT || 3000;
server.on('request', request);
server.listen(port, function() {
console.log('Server on port: %d', port);
});
function request(request, response) {
var store = '';
request.on('data', function(data)
{
store += data;
});
request.on('end', function()
{ console.log(store);
response.setHeader("Content-Type", "text/json");
response.setHeader("Access-Control-Allow-Origin", "*");
response.end(store)
});
}
My repository:
FolderRepository
public
- js folder
- img folder
- css folder
- index.ejs
server.js
app.js
Because your server is running on the other port. This is your port
var port = process.env.PORT || process.env.VCAP_APP_PORT || 3000;
and in ajax request you need to post to the url http://localhost: + your port
And also every time when you receive a request, your request will attach a new event handler to the data event, so after 10 attached events you will get an warning message about the leaking of the memory.
This code works. The main difference is that I call http.createServer() and you get it from the app.js. Look into the app.js and see if the server is created appropriatly.
Try to see if your server is created correctly.
var http = require('http');
var port = 3000;
var proxy = http.createServer();
proxy.listen(port);
proxy.on('request', request);
function request(request, response) {
var store = '';
request.on('data', function (data) {
store += data;
});
request.on('end', function () {
console.log(store);
response.setHeader("Content-Type", "text/json");
response.setHeader("Access-Control-Allow-Origin", "*");
response.end(store)
});
}
I've successfully used nodejs and socket.io to send a large json file from a server to a client, but I'm stumped on the next step: I need to analyse the json, and only send changes to the client, so that I have very fast real-time updates on the client-side, without having to send the entire json every second. I fear I'm missing something really basic. It's currently sending the entire json over and over. I see where that's happening, I just don't see how to send, instead, only the CHANGES. Ideas?
Server:
/*************************** Require modules ********************************/
var app = require('express')()
, request = require('request')
, fs = require('fs')
, http = require('http')
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
/************************* Start socket server ******************************/
server.listen(8127);
// socket.io
io.sockets.on('connection', function(socket){
var options = {
host: 'host.com',
port: 80,
path: '/api/tomyjson.json',
headers: {
'Authorization': 'Basic ' + new Buffer('username' + ':' + 'password').toString('base64')
}
};
function getStreams() {
http.get(options, function(response){
var data = "";
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function() {
socket.emit('news', JSON.parse(data));
});
});
}
setInterval(getStreams, 5000);
socket.on('message', function(data){
console.log(data)
})
socket.on('disconnect', function(){
})
});
Client JS:
var socket = io.connect('host.com:8127/');
socket.on('news', function (json) {
$.each(json.data, function(i, x) {
console.log(x.json.element);
$('#stream-container').prepend(x.json.element);
})
socket.emit('my other event', { my: 'data' });
});
socket.on('message', function(data){
// Do some stuff when you get a message
oldData += data;
document.getElementById('stream-container').innerHTML = oldData;
});
socket.on('disconnect', function(){
// Do some stuff when disconnected
});