Note: I am very new to express
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('id: ' + req.params.id + ' and name: ' + req.params.name);
});
var things = require('./things/things.js');
//both index.js and things.js should be in same directory
app.use('/things', things);
//Simple request time logger
app.use('/',function(req, res, next){
console.log("A new request received at " + Date.now());
//This function call is very important. It tells that more processing is
//required for the current request and is in the next middleware
//function/route handler.
next();
});
app.listen(3000);
I am learning about middleware functions and am trying to show a console.log message when I go to localhost:3000, but nothing shows up in my console, what am I missing here?
The problem is that Express passes requests to both middleware and route handlers in order of their declaration. If any of them are able to handle the request (by sending back a response), any other matching middleware or route handlers that got declared later won't get called.
That's what's happening in your situation, where your middleware is declared after the route handlers.
Try moving your middleware to the front:
app.use('/',function(req, res, next){
console.log("A new request received at " + Date.now());
next();
});
app.get('/', function(req, res) {
res.send('id: ' + req.params.id + ' and name: ' + req.params.name);
});
var things = require('./things/things.js');
app.use('/things', things);
First, you need to check the file structure. If index.js and things.js are in the same directory then you need to change the require function to var things = require('./things.js');
Next, verify that you are looking in the correct place, the console.log() message will appear in the terminal window where you loaded the express server, not in the console in your web browser.
The correct 'id' and 'name' of the parameters in get is like this
app.get('/:id/:name', function(req, res) {
res.send('id: ' + req.params.id + ' and name: ' + req.params.name);
});
The console module provides a simple debugging console that is similar
to the JavaScript console mechanism provided by web browsers. https://nodejs.org/api/console.html
Node Server generated console.log message in our terminal logs (Not on the browser).
https://expressjs.com/en/starter/hello-world.html
Related: https://www.twilio.com/blog/guide-node-js-logging
Related
The Problem occurs while sending GET or any request with parameters in the URL.
for example my
index.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/:name", function (req, res) {
let name = req.params.name;
console.log("Hello " + name + " from /:name");
res.send("Hello " + name + " from /:name");
});
app.get("/", function (req, res) {
console.log("Hello world from /");
res.send("Hello world from /");
});
app.listen(3000, () => {
console.log("Server is running on port " + 3000)
});
For http://localhost:3000/ it's working perfectly fine.
the Problem is occurring when we try to hit /:name route
when we use URL http://localhost:3000/?name=NODE it is going to the same route as above. in /
But the crazy part is when we put http://localhost:3000/NODE which is simply a new different route that is not implemented.
It is getting the response from :/name which doesn't make any sense.
is it a BUG or I am doing something wrong or is it something new I am not aware of?
I am currently using Windows11,
this problem also occurs in my friend's PC who uses Ubuntu
When you define route as
/:name
That's called path parameter and it's used like this :
GET /yourname
And that's why this works :
GET /NODE
What you"re using to call the endpoint (?name=xxx) is called query parameter, you can get that name from '/' endpoint like this :
let name = req.query.name;
I think you're almost there, but /:name does not match /?name=, but it does match /NODE.
This is exactly what's expected to happen. If this surprised you, go re-read the documentation because it should be pretty clear on this.
I think I am confused between query parameters and params.
Let:
given this URL http://www.localhost:3000/NODE?a=Debasish&b=Biswas
We will have:
req.query
{
a: 'Debasish',
b: 'Biswas'
}
req.params
{
param1: 'NODE'
}
Here I am sending a query but want to receive params. That is where I go wrong.
For better understanding check :
Node.js: Difference between req.query[] and req.params
With Node.js, Express and Mongoose, I am serving several static files synchronously within multiple sub-directories with the following code (which works fine):
fs.readdirSync(__dirname + "/../../../np-site/themes/default/client/")
.forEach(function (dir) {
app.use(express.static(__dirname +
"/../../../np-site/themes/default/client/" + dir)
);
});
However, part of the url must be dynamic depending on a database entry value:
express.static(__dirname + "/../../../np-site/themes/" + theme + "/client/" + dir)
I have tried several different ways, to no avail. The following is the first attempt I made, which made the most sense to me at the time (the App model is a single object that can only be updated and retrieved):
App.find(function (err, appSettings) {
fs.readdirSync(__dirname + "/../../../np-site/themes/" + appSettings[0].theme +
"/client/").forEach(function (dir) {
app.use(express.static(__dirname + "/../../../np-site/themes/" +
appSettings[0].theme + "/client/" + dir)
);
});
});
This however does not work, and no static files are served as a result.
The object that I need to access is available (discovered via console.log), but something is not right.
The browser console does return an infrequent error message stating the MIME type of the files (CSS) is not correct, but I believe this is because the app cannot find correct directories (removing the method altogether has the same result).
I'm thinking that it has something to do with app.use within a Mongoose method, but I am not certain.
Could someone please shed some light towards this frustrated soul? I feel as though I am on the wrong path.
The problem is that you're adding your middleware asynchronously (because App.find() is most likely performing an asynchronous action), which causes your dynamic middleware to get added (probably) after all of your statically defined middleware and route handlers.
Express executes middleware and route handlers in the order that they are added.
The solution would be to delay adding any other middleware or route handlers until after your fs.readdirSync() (but inside your App.find() callback). A simple way to do this is to simply put your other middleware and route handler additions inside a function that you call after your fs.readdirSync():
var baseThemePath = __dirname + "/../../../np-site/themes/";
App.find(function (err, appSettings) {
var themePath = baseThemePath + appSettings[0].theme + "/client/";
fs.readdirSync(themePath).forEach(function(dir) {
app.use(express.static(themePath + dir));
});
setupStatic();
});
function setupStatic() {
app.use(express.static('public'));
app.get('/', function(req, res) {
res.send('Hello world');
});
// ...
}
I'm very new to node and trying to set up a simple backend solution to handle the routes in my Backbone application. Right now I'm routing everything to index.html. My problem is when I make a data request the response comes back with Content-Type:text/html; charset=UTF-8 when I need it to be Content-Type:application/json. I know I need to set this header somewhere but not sure where and was wondering if someone could help?
JS
var express = require('express');
var port = 8000;
var server = express();
server.use('/dist', express.static(__dirname + '/dist'));
server.get('scripts/data/*.json', function(req, res) {
return res.json({
success: true
})
});
server.get('*', function(req, res){
return res.sendFile(__dirname + '/index.html');
});
server.listen(port, function() {
console.log('server listening on port ' + port);
});
You need to do it in get method
add
res.setHeader("Content-Type", "application/json");
before sendFile
https://nodejs.org/api/http.html#http_response_setheader_name_value
You can also use middleware:
In express you can use express.static(root, [options])
Where one of option can be: setHeaders function
Check these links:
Send additional http headers with Express.JS
http://expressjs.com/api.html
http://expressjs.com/starter/static-files.html
Here's another approach.
As pointed out in the answer above, you can pass additional parameters to express.static.
So, in order to serve your *.json files you should put this code about your * route:
app.use('/scripts', express.static(__dirname + '/scripts'), {
setHeaders: function(res) {
res.setHeader("Content-Type", "application/json");
}
});
I'm attempting to validate that my client can post info to it's server. I've set up this 'route' in my Express server.
// server.js this is the server for the PvdEnroll application.
//
var express = require("express"),
http = require("http"),
mongoose = require( "mongoose" ),
app = express();
// static file directory for default routing
app.use(express.static(__dirname + "/client"));
app.use(express.urlencoded());
// create Express-powered HTTP server
http.createServer(app).listen(3000);
console.log("Server listening at http://127.0.0.1:3000/");
// set up a post route in the server
app.post("/selections", function (req, res) {
console.log("data has been posted to the server!");
});
app.post("/selections", function (req, res) {
console.log("Some data has been posted to the server from app.js");
})
The client uses this file:
var main = function () {
"use strict";
$.getJSON("../data/checkBoxesA.json", function(checkBoxTxt) {
checkBoxTxt.forEach(function (data) {
var $checkbox = "<input type ='checkbox' name = "
+ data.label + "id = 0 UNCHECKED/>";
$(".enroll_actions").append($checkbox);
$(".enroll_actions").append(' ' + data.label + "<br/>");
$(".enroll_actions").append(' ' + data.note + "<br/>");
$(".enroll_actions").append(' '+ "<br/>");
});
});
$(".comment-input").on("click", function (event) {
console.log("Hello World!");
// here we'll do a post to our selections route
$.post("selections", {}, function (response) {
console.log("Client says - We posted and the server responded!");
console.log("Response from server :", response);
console.log("STUBB1");
});
});
console.log("STUBB2");
};
$(document).ready(main);
In the Chrome console I'm getting:
POST file:///Users/*******/Projects/r_PE/app/PvdEnroll/client/html/selections net::ERR_FILE_NOT_FOUND
A path is being sought but a tutorial's example (which works!) and is structurally identical to mine(?) uses a name i.e. "selections" to establish a route between client and server.
I'm running the server on my Mac using Virtual Box and Vagrant.
Thanks for any clarification.
On restarting the server the log message is now "POST 127.0.0.1:3000/html/selections 404 (Not Found).
Okay. This is some helpful information!
Basically, your file structure is more or less this (some file names will be different, just look at the general structure):
Node.js code (including main .js file and the module.json)
client: a folder for your static content
html: a folder
index.html: the file you are currently using
Anyway, jQuery.post() is fed a relative path (as apposed to an absolute path). That means that, based on the location of where the code was, it will "guess" the location of the file.
That means that it was trying to find a route at [locahost:port]/html/selections when your server is listening at [localhost:port]/selections! You'll need to have jQuery post to /selections instead of just selections.
For more information, this blog post is helpful (relative paths work the same in Javascript/CSS). The helpful snippet:
Here is all you need to know about relative file paths:
Starting with "/" returns to the root directory and starts there
Starting with "../" moves one directory backwards and starts there
Starting with "../../" moves two directories backwards and starts there (and so on...)
To move forward, just start with the first subdirectory and keep moving forward
So I have built a html form to interact with Slack. Currently my js code looks like this.
$("#submitemail").click(function(){
$.post(
"https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN",
JSON.stringify({'text':'invite request from: '+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
if anyone were to just copy this right out of my html file they could just run a console command and change the JSON and bombard my slack group with massive amounts of nonsense until they hit the API call limit.
What I am wondering is if I could store this in my index.js (I am using a node.js template) as a var and then call it in the html.
Any options or advice is greatly appreciated I am very new to this.
My structure is:
Slack App
|_node_modules
| |_express
|_public
| |_index.html
| |_node.svg (idk what this does)
|_.gitignore
|_app.json
|_index.js
|_package.json
|_procfile
|_README.md
the code for my index.js is just
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
I can throw in my full html if you want its just a basic modal w/ a button to click to execute the form and pull the email.
Disclaimer: this code is untested
You would basically do something like this:
index.js (commented to explain what i added):
var express = require('express');
// install request module
var request = require('request');
var app = express();
// make a new route that you can call from the client side
app.get('/getSlackData', function(req, res) {
//variable to hold your response from slack
var slackResponse;
//make the request to slack
var slackUrl = "https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN""
request(slackUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
slackReponse = response;
} else {
console.log(error);
});
return slackResponse;
});
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
So we added a new route, that is basically an API you can call from the client side, it will return the JSON object that you got from Slack. You can pretty much leave your client side code the same, just change the route you're calling:
$("#submitemail").click(function(){
$.post("/getSlackData",
JSON.stringify({'text':'invite request from:'+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
I hope I understood your question correctly, this should at least get you pointed in the right direction.