simple put request for nodejs without express - node.js

I need to be able to upload a zip file to a brightsign unit and thinking of creating a rest api which I can make a put request to send the zip file.
But the problem is that all examples I find is using frameworks such as express. Is it possible to make a rest API handling a PUT requst in nodejs without using extra frameworks?
The problem is that I can only use modules that does not need a "configuration" step on the brightsign player. So I can use modules that only contain plain javascript (I hope my explanation makes sense).

Vanilla (NodeJS HTTP API)
You will need to listen for the PUT somehow :
const http = require('http');
const querystring = require('querystring');
const server = http.createServer().listen(3000);
server.on('request', function (req, res) {
if (req.method == 'PUT') { //PUT Only
var body = '';
req.on('data', function (data){body += data;});
req.on('end', function () {
var PUT = querystring.parse(body);
console.log(PUT);
res.writeHead(200, {'Content-Type': 'text/plain'})
res.write('\n[request received successfully]\n'); res.end();
});
}else{res.end();}
});
You can test it out using curl :
curl -X PUT -d destPath=/home/usr/images -d fileName=selfie.png -d fileData=base64string localhost:3000
In express is much simpler, comment if you need an express example

Related

Is it possible to conditionally append Content encoding response header to node.js http-server module?

I'm trying to test Unity WebGL build locally. I've tried node.js http-server module. It serves uncompressed game made with Unity 2019 without problems.
However, it won't serve game made with 2020, which uses compression. If gzip or br compression is used, http-server does not send proper Content encoding header responses. Unity web player then complains that it can't parse the .gz or .br response, not knowing what it is.
I've tried writing simple js script to run instead of http-server module. However, it works strange, or not at all, and I don't have days to get into node.js.
var fs = require('fs'), http = require('http');
const path = require('path');
http.createServer(function (req, res) {
fs.readFile(__dirname + req.url, function (err,data) {
if (err) {
res.writeHead(404);
res.end(JSON.stringify(err));
return;
}
var ext = path.extname(req.url);
if (ext == ".br") {
res.writehead(200, {'content-encoding': 'br'});
}
else {
res.writehead(200);
}
res.end(data);
});
}).listen(8080);
Is there any way to make node.js run its http-server module but append Content encoding response header depending on url? Or can I correct this script to achieve desired behaviour?
Thank you!

Can I pass multiple functions to an http.createServer in NodeJS?

I'm completely new to server development and NodeJS, so my apologies if this question sounds stupid or if such a question already exists.
I was following a simple NodeJS tutorial and building a simple "Hello World" server. I noticed that http.createServer took only one function as its argument.
http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.end("Hello World");
}.listen(8080);
I tried passing another function to it like the following:
var http = require('http');
http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type':'text/html'});
res.end("Hello World");
},
function (req, res) {
res.write("Blahblah");
res.end();
}
).listen(8080);
But hitting localhost:8080 returned only Hello World.
So I was wondering if I could pass multiple functions to it and if not, then why.
Thank you for your time
You cannot pass multiple functions. If you want multiple listeners for incoming requests, you can just register another listener for incoming requests:
const server = http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.end("Hello World");
}.listen(8080);
// add additional listener
server.on('request', function(req, res) {
if (req.url === "/goodbye") {
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end("goodbye");
}
});
Note: right from the doc for http.createServer(), it says this about the function parameter passed to http.createServer():
http.createServer([options][, requestListener])
The requestListener is a function which is automatically added to the 'request' event.
Doc for the request event is here.
As others have said, it is pretty rare to use a plain http server like this because some simple routing is nearly always helpful and a lightweight framework like Express offers very useful features without really getting in the way of anything you might want to do. In the case of Express, you'd use code like this:
const express = require('express');
const app = express();
// define handler for /goodbye URL
app.get('/goodbye', function(req, res) {
res.send("goodbye");
});
// define handler for /hello URL
app.get("/hello", function(req, res) {
res.send("hello");
});
const server = app.listen(8080);
Here express, keeps a list of the URLs that you wish to handle and then listens for each incoming request, compares it against the URLs you wanted to handle and calls the appropriate route handler. It has lots of other features for routing too such as middleware, wildcards, parameterized URLs, etc...
I'd recommend you use something like express if you want multiple routes:
const express = require('express');
const app = express();
app.get('/hello', (req, res) => res.send('Hello World!'));
app.get('/world', (req, res) => res.send('Hello World!'));
app.listen(3000, () => console.log('Example app listening on port 3000!'));
Node.js provides you with the features to create your own webserver from scratch, unless you want to create a whole new framework i would recommend using something like expressjs.
Have a look at this following tutorial if you're a newbie and want to create restful services.
Build a RESTful API Using Node and Express 4 | Scotch.io
Its a fairly simple and straightforward tutorial

Node JS: Where is my POST data?

I have no lack with sending POST request to node js server. I have a simple request and a simple server.
My server code is:
var http = require('http');
var bodyParser = require('body-parser');
http.createServer(function (req, res) {
console.log(req.body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/')
my client request code is:
var val = JSON.stringify({ city:"SomeCity", name:"MyNameIsHere" });
alert(val);
$.ajax({
url: 'http://127.0.0.1:1337',
type: 'POST',
data: { value: val},
success: function(result) {
alert('the request was successfully sent to the server');}
});
So I suppose to get SomeCity and MyNameIsHere strings in the request body at the node js server, but the req.body field is undefined. Have to say that I open my test.html with request code locally with URL like this:
file:///D:/Projects/test.html
May be Im blind and overseen something trivial, but I have no idea what:)
Have to say that I open my test.html with request code locally with URL like this:
file:///D:/Projects/test.html
You're trying to post cross-domain, which you cannot do in this case. Serve your HTML over HTTP so that you can make a POST. If you use your browser's development tools, you will see that the request will never hit your Node.js server (except for a possible pre-flight request for CORS).
Another problem is that you're not actually using body-parser. If you want the post data, you will have to read from req like a stream.
You are including "body-parser" in var bodyParser = require('body-parser');, but you never actually use it. It won't magically parse the request for you. The default request object does not have a body property... see the documentation.
If you want to use the body-parser module, you should probably use express.js and read the documentation on how to connect it as middleware.
If you want to get the body using the built-in http server, you need to consume the request object first using something like this:
if (req.method == 'POST') {
var body = '';
req.on('data', function(data) {
body += data;
if (body.length > 1000000) {
req.connection.destroy();
}
});
req.on('end', function () {
console.log(req.body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});
}
Adding express library and bodyparser as middleware did the trick. However I could use the code from neelsg answer but working with built-in http server and handling Post data by my own is too burdensome.
So piece of my working code is here:
var express = require('express');
var http = require('http');
var url = require('url');
var bodyParser = require('body-parser');
var app = express();
app.use(express.bodyParser(
{
keepExtensions: true,
limit: 30*1024*1024 // lets handle big data
}
));
app.use(bodyParser.urlencoded());
Bodyparser by default can handle only 100Kb data in the post request, so I had to increase limit using its config options.

jQuery .load() from local httpd (node)

Node.js server
var http = require("http");
http.createServer(function(request,response){
console.log("client connected");
response.writeHeader(200,{"Content-type": "text/html"});
response.write("Hello ;-)");
response.end();
}).listen(9090);
I try to load the server output into a div with the ID "myDisplayField":
$("#myDisplayField").load("http://localhost:9090");
(The HTML-File lies on my local httpd)
The issu I'm having with that is that the node server may show that he got a request from ajax ("client connected"), but "Hello ;-)"/the site content doesn't get loaded into #myDisplayField as expteced.
If I set up a webserver like Apache and put a index.html with "Hello ;-)" in htdocs, the whole thing works just fine.
What am I doing wrong?
I just tried your code, and navigating to localhost:9090 displays the 'hello' body as expected.
It may be that jquery's load() method looks for other data - for example, content-type in the header - that your very simple response doesn't provide. Instead of building every http response individually, you should use a higher-level server like express:
var express = require('express');
var app = express();
app.use(function(req, res, next) {
res.send('Hello');
});
app.listen(9090);

node.Js - how run different pages?

so when enter the url: http://mysite.com/ there will be loading the server.js file (the index file). I want load the account.js when I enter url http://mysite.com/account.
How to do that?
In server.js , on top include account.js >
var account = require("./account");
In your createServer function in nodejs, you check if the URI is /account >
//Create Server
http.createServer(function (request, response) {
// Parse the entire URI to get just the pathname
var uri = url.parse(request.url).pathname, query;
if (uri == "/account") //If it's mysite.com/account
{
request.setEncoding("utf8");
request.content = '';
//call account.whatever() to route to your account functionality
//send the response from it
}
else if (uri == "/") //It's mysite.com
{
//call whatever you have in the current server.js
}
}).listen(8080);
Nodejs is a daemon. It doesn't load scripts every time you making request.
You can use something like that:
var severs = require('server.js'),
accounts = require('accounts.js');
require('http').createServer(function (req, res) {
var path = require('url').parse(req.url).pathname;
res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
if (path == '/account') {
res.end(accounts.run());
} else {
res.end(severs.run());
}
}).listen(80);
It is better to use request routers - see connect and express NPM modules. Manual path comparison does not scale - it will turn your code into nightmare as you add more and more URLs.
For a standalone router, see clutch NPM module, but router inside connect is more mature and can be used in a standalone way. express is an extension of connect, so it uses the router from connect.

Resources