I have a movie-finding app that makes API calls in the backend. During initialization I need to load some JSON files: one (lang.json) contains a list of languages for searching purposes, the other (stored in the config variable) is used to get a link to the movie poster.
How would I ensure the loading of these files is completed before an HTTP request is made? One solution I can think of involves putting the calls to app.get() and app.listen() inside fs.readfile()'s callback. But is there a better way? Web development is totally new to me.
var express = require('express');
var app = express();
var fs = require('fs');
var request = require('request');
var merge = require('merge');
require('dotenv').config();
var apiKey = process.env.API_KEY;
var config = {};
app.use(express.static('view'));
// TODO load config and lang before below code
app.get('/lang', function(req, res) {
fs.readFile('lang.json', function(err, data) {
if (err) throw err;
res.json(JSON.parse(data));
});
});
app.get('/genres', function(req, res) {
request.get({
url: 'http://api.themoviedb.org/3/genre/movie/list',
qs: {api_key: apiKey}
}, function(error, response, body) {
res.json(JSON.parse(body).genres);
});
});
app.get('/randomMovie', function(req, res) {
request.get({
url: 'https://api.themoviedb.org/3/discover/movie',
qs: merge(req.query, {api_key: apiKey})
}, function(error, response, body) {
body = JSON.parse(body).results;
var len = body.length;
var i = Math.floor(Math.random() * len);
var movie = body[i];
// movie.poster_path = movie.images.base_url + movie.images.poster_sizes[6] + movie.poster_path;
res.json(movie);
});
});
app.listen(3000, function() {
console.log('server started on port 3000');
});
The easiest way is to just use fs.readFileSync() before your call to app.listen(). For example:
var lang = fs.readFileSync('lang.json');
app.get('/lang', function(req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(lang);
});
// ...
Just be aware that the contents of lang will not automatically update if the contents of lang.json change on disk during the lifetime of your node process.
Related
I am beginning to code in Javascript and Nodejs. I am checking if a post call has been made to recFile and accept the file sent. For all other http requests made I want to return a static HTML page. When I tried res.redirect it said 'res.redirect is not a function'
const bodyparser = require('body-parser');
var http = require('http');
var formidable = require('formidable');
var fs = require('fs');
const express =require('express');
const { response } = require('express');
const app = express();
http.createServer(function (req, res) {
if (req.url == '/recFile') {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var oldpath = files.filetoupload.path;
var newpath = './Uploads/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
})
});
} else {
// Need to send user here to a HTML page. But don't know how to do that.
// res.write is not viable as there is a lot of HTML lines of code.
return res.end();
}
}).listen(9000);
Try
response.writeHead(302, {
'Location': 'your/404/path.html'
//add other headers here...
});
response.end();
(Information from Nodejs - Redirect url, did you google it properly?)
I want my the /image of my app to return a random image, how can I do that?
app.js:
const app = express();
app.get('/image', async (req, res) => {
const url = 'https://example.com/images/test.jpg';
res.send(/**/); // How do I send the image binary data from the url?
});
index.html
In HTML, this image actually shows the content of the image https://example.com/images/test.jpg
<img src="https://my-app.com/image" />
We have the same problem, and this is my solution for this using request package, so you have to yarn add request or npm i request first.
your code should be like this
const request = require('request');
const express = require('express');
const app = express();
app.get('/image', async (req, res) => {
const url = 'https://example.com/images/test.jpg';
request({
url: url,
encoding: null
},
(err, resp, buffer) => {
if (!err && resp.statusCode === 200){
res.set("Content-Type", "image/jpeg");
res.send(resp.body);
}
});
});
There is res.sendFile in Express API
app.get('/image', function (req, res) {
// res.sendFile(filepath);
});
const express = require("express");
const https = require("node:https");
const app = express();
const port = 3000
app.get("/", function(req, res){
const url = "https://api.openweathermap.org/data/2.5/weather?q=Paris&units=metric&appid=65441206f989bc53319e2689fccdc638";
https.get(url, function(response){
response.on("data", function(data){
const weatherData = JSON.parse(data)
const icon = weatherData.weather[0].icon
const imageUrl = "http://openweathermap.org/img/wn/" + icon + "#2x.png"
res.write("<img src=" + imageUrl + " ></img>")
res.send();
})
});
})
You can save all such image links in json or any of your choice data file and get from them randomly and forward and pass them through variable in response. Like: res.send(imgURL: 'https://example.com/images/test.jpg'); or you can pass url variable in init.
I'm trying to serve multiple audio files in the node.js server, but the server sometimes fails when multiple clients try to access. How can I remedy this?
express = require('express');
const http = require('http');
const path = require('path');
const fs = require('fs');
const app = express();
app.get('/', function (request, response) {
let fpath = base_dir + filenames[getIndex(filenames.length)];
let filestream = fs.createReadStream(fpath);
var d = new Date();
filestream.on('open', function() {
let stats = fs.statSync(fpath);
let fileSizeInBytes = stats["size"];
response.writeHead(200, {
"Accept-Ranges": "bytes",
'Content-Type': 'audio/mpeg',
'Content-Length': fileSizeInBytes});
filestream.pipe(response);
});
})
app.listen(3000, function () {
console.log('Audio file provider listening on port 3000');
})
You're using fs.statSync() which will block the thread also listening for incoming connections. Instead you should switch to the asynchronous version fs.stat().
app.get('/', (req, res) => {
let fpath = base_dir + filenames[getIndex(filenames.length)]
let d = new Date()
fs.stat(fpath, (err, stats) => {
// Handle Error when trying to get file stats
// Respond with 500 Internal Server Error
if (err) {
console.log(err)
return res.sendStatus(500)
}
let {size} = stats
res.status(200)
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Type', 'audio/mpeg')
res.setHeader('Content-Length', size)
fs.createReadStream(fpath).pipe(res)
})
})
You're already using express, no need to reinvent the wheel http://expressjs.com/en/4x/api.html#res.sendFile
app.get('/', function (request, response) {
let fpath = base_dir + filenames[getIndex(filenames.length)];
response.sendFile(fpath, function(err) {
//Handle err if any
});
})
Using Node.js and Express, my first route determines the client's language :
var express = require('express'),
app = module.exports = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
ent = require('ent'),
fs = require('fs'),
path = require('path'),
request = require('request');
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
var ip = req.ip;
request('http://freegeoip.net/json/' + ip, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
var code = data.country_code.toLowerCase();
}
});
res.render('index.ejs');
});
Then I need to pass code to index.ejs to display the appropriate language.
Some people suggest to use Angular to share a scope, but Angular isn't defined in my app, only in index.ejs. I'm not sure if I should add it to app.js or not.
Others suggest to use module.exports on the app but require doesn't work on the front end either.
What is a good way to do it ?
Call res.render inside the callback after you've called http://freegeoip.net, and pass any data needed to render the view as an object parameter, to res.render, i.e.
app.get('/', function (req, res) {
var ip = req.ip;
request('http://freegeoip.net/json/' + ip, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
var code = data.country_code.toLowerCase();
res.render('index.ejs', {
code: code
});
}
});
});
I want to display all the output from pokecli.py on a web page that can be accessed from http://192.168.32.100:8081. Currently I am getting a "connection refused" from Chrome, but no errors when running node myscript.js.
I am new to Node and I am not exactly sure if this is right. I want to display the output in real time. I know this is possible even without NGINX since I can get output from the following example code by opening http://192.168.32.100:8080:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, '192.168.0.251');
console.log('Server running at http://192.168.0.251:8080/');
Here is my code:
var http = require('http');
var PythonShell = require('python-shell');
var express = require('express');
var app = express();
// Options to be used by request
var options = {
host: '127.0.0.1',
port: '8081'
};
// Callback function is used to deal with response
var callback = function(response){
// Continuously update stream with data
var body = '';
response.on('data', function(data) {
body += data;
PythonShell.run('pokecli.py', function (err) {
if (err) throw err;
console.log('finished');
});
});
response.on('end', function() {
// Data received completely.
console.log(body);
});
}
// Make a request to the server
var req = http.request(options, callback);
app.get('/', function (req, res) {
res.send('Hello World!'); // This will serve your request to '/'.
});
app.listen(8081, function () {
console.log('Example app listening on port 8081!');
});
req.end();