Node.js: get path from the request - javascript

I have a service called "localhost:3000/returnStat" that should take a file path as parameter. For example '/BackupFolder/toto/tata/titi/myfile.txt'.
How can I test this service on my browser?
How can I format this request using Express for instance?
exports.returnStat = function(req, res) {
var fs = require('fs');
var neededstats = [];
var p = __dirname + '/' + req.params.filepath;
fs.stat(p, function(err, stats) {
if (err) {
throw err;
}
neededstats.push(stats.mtime);
neededstats.push(stats.size);
res.send(neededstats);
});
};

var http = require('http');
var url = require('url');
var fs = require('fs');
var neededstats = [];
http.createServer(function(req, res) {
if (req.url == '/index.html' || req.url == '/') {
fs.readFile('./index.html', function(err, data) {
res.end(data);
});
} else {
var p = __dirname + '/' + req.params.filepath;
fs.stat(p, function(err, stats) {
if (err) {
throw err;
}
neededstats.push(stats.mtime);
neededstats.push(stats.size);
res.send(neededstats);
});
}
}).listen(8080, '0.0.0.0');
console.log('Server running.');
I have not tested your code but other things works
If you want to get the path info from request url
var url_parts = url.parse(req.url);
console.log(url_parts);
console.log(url_parts.pathname);
1.If you are getting the URL parameters still not able to read the file just correct your file path in my example. If you place index.html in same directory as server code it would work...
2.if you have big folder structure that you want to host using node then I would advise you to use some framework like expressjs
If you want raw solution to file path
var http = require("http");
var url = require("url");
function start() {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
source : http://www.nodebeginner.org/

simply call req.url. that should do the work. you'll get something like /something?bla=foo

You can use this in app.js file .
var apiurl = express.Router();
apiurl.use(function(req, res, next) {
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
next();
});
app.use('/', apiurl);

req.protocol + '://' + req.get('host') + req.originalUrl
or
req.protocol + '://' + req.headers.host + req.originalUrl // I like this one as it survives from proxy server, getting the original host name

Based on #epegzz suggestion for the regex.
( url ) => {
return url.match('^[^?]*')[0].split('/').slice(1)
}
returns an array with paths.

A more modern solution that utilises the URL WebAPI:
(req, res) => {
const { pathname } = new URL(req.url || '', `https://${req.headers.host}`)
}

I've used this const { pathname } = req?._parsedUrl || {}; and it worked for me

Combining solutions above when using express request:
let url=url.parse(req.originalUrl);
let page = url.parse(uri).path?url.parse(uri).path.match('^[^?]*')[0].split('/').slice(1)[0] : '';
this will handle all cases like
localhost/page
localhost:3000/page/
/page?item_id=1
localhost:3000/
localhost/
etc. Some examples:
> urls
[ 'http://localhost/page',
'http://localhost:3000/page/',
'http://localhost/page?item_id=1',
'http://localhost/',
'http://localhost:3000/',
'http://localhost/',
'http://localhost:3000/page#item_id=2',
'http://localhost:3000/page?item_id=2#3',
'http://localhost',
'http://localhost:3000' ]
> urls.map(uri => url.parse(uri).path?url.parse(uri).path.match('^[^?]*')[0].split('/').slice(1)[0] : '' )
[ 'page', 'page', 'page', '', '', '', 'page', 'page', '', '' ]

Related

Connect Microsoft Azure Machine Learning Studio API using Vue Axios or using Express Server?

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);
})

Simple Node.js server without Express - piping HTML files to response

I am trying my hand at making a simple Node.js server without Express and this where I actually learn a bit more about the down and dirty of actually server files and data on requests based on paths request and basic HTTP stuff.
I have this straightforward server like so:
var http = require('http');
const PORT = 6969;
var allRoutes = require('./routes/all');
var server = http.createServer(allRoutes);
server.listen(PORT, function () {
console.log("Server listening on: http://localhost:%s", PORT);
});
and then I have one "middleware" function like so that handles all requests:
var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');
function handleRequest(req, res) {
var requestUrl = url.parse(req.url);
var fsPath;
if (requestUrl.pathname === '/') {
fsPath = path.resolve(appRootPath + '/view/index.html');
}
else {
fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
}
fs.stat(fsPath, function (err, stat) {
if (err) {
console.log('error occurred...' + err);
return end(req, res);
}
try {
if (stat.isFile()) {
res.writeHead(200);
fs.createReadStream(fsPath).pipe(res);
}
else {
res.writeHead(500);
}
}
finally {
end(req, res);
}
});
}
function end(req, res) {
res.end();
}
module.exports = handleRequest;
the problem I am having is that my function doesn't seem to pipe the response to the browser. The browser shows no evidence of the data come from index.html, which is a barebones .html HTML5 file.
I stole the example, and am surprised it's not really working. Anyone have an idea? I know for sure that the fs.stat function is not experiencing an error and then it is streaming the index.html file, it just doesn't seem to be streaming to the right place...
For starters:
if (requestUrl.pathname = '/')
should be:
if (requestUrl.pathname === '/')
Your code was assigning, not comparing.
In addition, the .pipe() is asynchronous, but you are calling res.end() BEFORE it gets to do it's job in your finally{} block which closes the response stream and stops your pipe from doing anything. By default .pipe() will close the write stream by itself, so you don't need the res.end() at all when using .pipe().
You can change the code to this:
var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');
function handleRequest(req, res) {
var requestUrl = url.parse(req.url);
var fsPath;
if (requestUrl.pathname === '/') {
fsPath = path.resolve(appRootPath + '/view/index.html');
}
else {
fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
}
fs.stat(fsPath, function (err, stat) {
if (err) {
console.log('error occurred...' + err);
return end(req, res);
}
try {
if (stat.isFile()) {
res.writeHead(200);
fs.createReadStream(fsPath).pipe(res);
}
else {
res.writeHead(500);
end(req.res);
}
}
catch(e) {
end(req, res);
}
});
}
function end(req, res) {
res.end();
}
module.exports = handleRequest;

Saving image to node.js server without express.js

So I have been wondering how to save an image to node.js server without the use of express.(just learning node and want to make everything myself to learn node better, without express).
So far I have a form with the image as only input which I send with a post request. This is what I have so far on my server, which does not log anything.
if(req.method === 'POST') {
if (req.url === '/upload') {
req.on('error', function(e) {
console.log('Problem with request: ' + e.message);
});
res.writeHead(200, {'Content-Type': 'image/jpg; charset=utf8'});
req.on('data', function (chunk) {
fs.writeFile(__dirname + "/uploads/dada.jpg", chunk, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
});
}
}
This is my form:
<form method="post" action="/upload" enctype="multipart/form-data">
EDIT: I fixed most of the problems, but the file is only saved as an image, but cannot be viewed like one. (Something is wrong with the content-type I guess, but don't know how to fix it)
Here is fiddle of my whole app. I know I need to separate it in different modules, but I will do that later
I completely forgot about this old question but now that I see it has quite some views, here is the solution I found:
var port = 1357;
var http = require('http'),
path = require('path'),
mime = require('mime'),
fs = require('fs'),
GUID = require('GUID'),
formidable = require('formidable'),
util = require('util');
var app = http.createServer(function (req, res) {
if (req.method === 'POST') {
if (req.url === '/upload') {
req.on('error', function (e) {
console.log('Problem with request: ' + e.message);
});
var fileDirectory = __dirname + '/db/',
form = new formidable.IncomingForm();
form.keepExtensions = true;
form.uploadDir =fileDirectory;
form.parse(req, function (err, fields, files) {
if (err) throw (err);
var pic = JSON.stringify(util.inspect(files)),
upIndx = pic.indexOf('db'),
path = pic.slice(upIndx + 6, upIndx + 42);
res.writeHead(200, {
'Content-Type': 'text/html'
});
fs.readFile('views/index.html', function (err, page) {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.write(page);
res.write('<div>Download Link: </div><div>' + fileDirectory + path + '</div>');
res.end();
});
});
}
} else {
//not important for question, handle other request
}
});
app.listen(port);
console.log('Server running on port: ' + port)

Basic attempt at using NodeJS

I tried to follow an example on the web for creating a NodeJS server and router, but have ran into problems. What follows is primarily the example with a bit of other code.
Index.js
var server = require("./server");
var router = require("./router");
server.start(router.route);'
Router.js
var fs = require("fs");
function route(filename) {
fs.readFile(filename, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
console.log("About to route a request for " + filename);
data = JSON.parse(data);
})
}
exports.route = route;
Server.js
var http = require('http');
var url = require("url");
function start(route) {
function onRequest(request, response) {
var filename = request.url.substr(1);
// call for specific json file here
if (filename == "favicon.ico") {
response.writeHead(200, {'Content-Type': 'image/x-icon'} );
response.end();
console.log('favicon requested');
return;
}
else {
filename += ".json";
console.log("Request for " + filename + " received.");
response.writeHead(200, { 'Content-Type': 'application/json', "Access-Control-Allow-Origin":"*" });
response.write("" + route(filename),0,4);
response.end();
}
}
http.createServer(onRequest).listen(8124);
}
exports.start = start;
console.log('Server running at http://127.0.0.1:8124/');
The question I have is, among others, how does the route command work?
What I get when I browse to the server is 'undefined'. How do I get the actual json from the Router?
I tried: var result = route(filename); but that failed badly.
In essence, how to get the data from the router and write it to the response. If you haven't guessed, javascript and NodeJS is rather new to me.
Any pointers would be greatly appreciated.
Thank you.
Your route function has an async method, fs.readFile. You'll need to pass in a callback to the route function, so that it can return the data properly. Otherwise, route will return immediately with no data (since it's async) regardless if you have a return statement inside readFile.
router.js
function route(filename, callback) {
fs.readFile(filename, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
console.log("About to route a request for " + filename);
data = JSON.parse(data);
callback(data); // Call this function after the data is grabbed.
})
}
server.js portion:
response.writeHead(200, { 'Content-Type': 'application/json', "Access-Control-Allow-Origin":"*" });
route(filename, function (data) {
response.write("" + JSON.stringify(data),0,4);
response.end();
});

Node.js - Static fileserver not working

I'm trying to create a static fileserver in note.js, but it is not really working.
My fileserver.js code:
var http = require("http"),
sys = require("sys"),
path = require("path"),
url = require("url"),
filesys = require("fs"),
rootpath = "D:\\NodeJS\\WWW\\",
port = 3000;
http.createServer(function(request,response){
var my_path = url.parse(request.url).pathname;
var full_path = path.join(process.cwd(),rootpath+my_path);
path.exists(full_path,function(exists){
if(!exists){
response.writeHeader(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
}
else{
filesys.readFile(full_path, "binary", function(err, file) {
if(err) {
response.writeHeader(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
}
else{
response.writeHeader(200);
response.write(file, "binary");
response.end();
}
});
});
})
http.createServer(function(request,response){
var my_path = url.parse(request.url).pathname;
filesys.readFile(rootpath + my_path,response);
}).listen(port);
sys.puts("Server Running on 3000");
When I now try to open: localhost:3000/index.html (The index file is in the folder WWW), my webbrowser is just loading and loading something but not displaying anything. There is also no error in the console.
I hope you can help me!
JS
Are you trying to get directory listing with this program? If yes then use this.
var http = require('http');
var connect = require('connect');
var app = connect()
.use('/public', connect.static(__dirname + '/public'))
.use('/public', connect.directory(__dirname + '/public'))
.use(function(req, res){
res.end('hello world\n');
})
http.createServer(app).listen(3000);
// access it on http://localhost:3000/public
I have used connect module. connect.directory serves the directory listing and connect.static serves the static file.
Let me know if I have not understood you correctly.
Try This :
var fs = require('fs');
var http = require('http');
var path = require("path");
var url = require("url");
var settings = require("../settings");
http.createServer(function (request, response) {
var uri = url.parse(request.url).pathname;
var filetype = (uri.split("/static/")[1]).split(".")[1];
var filename = path.join(process.cwd(), uri);
fs.readFile(filename, function (error, content) {
if (error) {
response.writeHead(500);
response.end();
}
else {
response.writeHead(200, { 'Content-Type': settings.STATIC.HEADERS[filetype.toUpperCase()] });
response.end(content, 'utf-8');
}
});
}).listen(8000);
Add A settings File with something like this :
module.exports = {
DOMAIN: "localhost", // Runnimg Domain , Production Only
PORT: 8080, // Port Project Running On
PROJECT: __dirname, // project directory
DEFAULT_THEME: "default", // Default Theme for site
DB: { // Database Information and Credintials
HOST: "localhost",
USER: 'root',
PASSWORD: 'root',
DATABASE: 'sockets'
},
STATIC: { // Static Files and forlders information
EXTENSIONS: ['psd', 'docs', 'zip', 'rar', 'png'], // allowed to download extensions
HEADERS: {// MIME Types for diffrent types
PDF: 'application/pdf',
CSS: 'text/css',
JS: 'text/javascript',
HTML: 'text/html',
TXT: 'text/plain',
JPG: 'image/jpeg',
JPEG: 'image/jpeg',
GIF: 'image/gif ',
DOWNLOAD: 'application/octet-stream'
}
}
};
i Always like to have this file with everything that i will use everywhere.
and as you can see the code waits for a url like this :
http://domain:port/static/file.ext
you can change that in this line :
var filetype = (uri.split("/static/")[1]).split(".")[1];
Hope this helps

Categories

Resources