I was using express route like this and I want my urls to contain query strings initially.
app.get('/', function(req, res){
res.render('index', {});
});
app.get('/us01', function(req, res){
console.log('query: '+JSON.stringify(req.query));
res.render('templates/us01', {});
});
app.get('/benchmark', function(req, res){
res.render('templates/benchmark', {});
});
However, I never get my query strings printed no matter what query strings I append after /us01. For example, "localhost:9200/us01?a=1" req.query should get me {a:1}, correct? Is this a common thing? What am I missing here?
My app.js
"use strict";
var express = require('express');
var expApp = express();
var http = require('http').Server(expApp);
var path = require('path');
var bodyParser = require('body-parser');
// all environments
expApp.set('port', process.env.PORT || 5555);
expApp.set('views', __dirname + '/views');
expApp.set('view engine', 'ejs');
expApp.use(bodyParser.urlencoded({ extended: true }));
expApp.use(bodyParser.json());
expApp.use(express.static(path.join(__dirname, 'public')));
//----------------ROUTES--------------------------//
require("./routes/route.js")(expApp);
http.listen(expApp.get('port'), function(){
console.log('Node-Server listening on port ' + expApp.get('port'));
});
My indexController.js has :
$stateProvider
.state('us01', {
url: '/us01',
templateUrl: '/us01'
}).state('benchmark', {
url: '/benchmark',
templateUrl: '/benchmark'
})....
This simple code:
const express = require('express');
const app = express();
app.get('/us01', function(req, res) {
console.log(req.query);
res.send("ok");
});
app.listen(80);
Then, accessed by http://localhost/us01?a=1 produces this output in the console:
{ a: '1' }
Or, if I use:
console.log('query: ' + JSON.stringify(req.query));
Then, I see this in the console:
query: {"a":"1"}
So, clearly something else is wrong in your code.
"localhost:9200/us01?a=1" req.query should get me {a:1}, correct?
It should get you query: {"a":"1"} if the code you show is running on port 9200 on localhost.
Is this a common thing?
No. Something other than the code you show is busted because there's nothing wrong with just that bit of code.
What am I missing here?
Things to examine:
Are you getting any output in the console when you hit any of your expected routes?
Can you prove that your server is running and your browser is hitting your route handlers?
If you just do console.log(req.query), what output do you get?
Are you absolutely sure that you've killed any prior servers and started the server that corresponds to the code you show. People sometimes get fooled by a prior version of the server that is still running and doesn't actually contain the code they think they are running.
Are you 100% sure you are running your server on the desired port that matches the port in the URL you are using.
When all else fails, sometimes a computer reboot will make sure no prior versions of anything are still running.
Related
My goal is to port my existing Node-Express-Pug-Mongo website onto Amazon Web Services, but I'm running into an error with rendering Pug files on Lambda. Whenever I attempt to run res.render, the page shows this: {"message": "Internal server error"} after a timeout of 3000 milliseconds (from viewing the CloudWatch console).
I've tried throwing console.log everywhere to get more information on what is causing the error, but to no avail.
res.send works with text
res.sendFile works with the Pug file that I am trying to use in the function
res.render accepts a callback input, which I have attempted to use to catch errors, but no logs exist on the console.
I've tried different ways of inputting the pug file, as you can see for the five different get URLs. All of them do the same thing.
I've tried changing to Jade, but I get the same issues.
NOTE: On a local server, the syntax in render1 and render3 are the ones that work.
ALSO: On the local server, using callbacks does cause the function to hang. I have attempted this with and without callbacks, and the issue is the same.
'use strict'
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const router = express.Router();
app.set('view engine', 'pug');
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
app.set('views', path.join(__dirname, 'views'));
router.get('/sendfile', function(req, res){
res.sendFile(__dirname+"/views/test.pug");
});
router.get('/sendtext', function(req, res){
res.send('hello!');
});
router.get('/render1', function(req, res){
res.render('test', {}, function(err){
console.log(err);
});
});
router.get('/render2', function(req, res){
res.render('.test', {}, function(err){
console.log(err);
});
});
router.get('/render3', function(req, res){
res.render('./test', {}, function(err){
console.log(err);
});
});
router.get('/render4', function(req, res){
res.render('./views/test', {}, function(err){
console.log(err);
});
});
router.get('/render5', function(req, res){
res.render(__dirname+'/views/test', {}, function(err){
console.log(err);
});
});
app.use('/', router);
// Export your express server so you can import it in the lambda function.
module.exports = app;
None of these render functions work. It always times out after 3 seconds and returns {"message": "Internal server error"}. I've tried everything I could think of. Is this an Express issue? Do I have to do something different to configure Pug? It works exactly as expected when I use the exact same module on a local Node.js server.
After a lot of digging, I figured out the issue.
My Lambda function ("server") wasn't allocated enough RAM. When I attempted to load Pug, it would overload and crash.
The default is 128MB, so turning it up to 384MB-ish worked fine.
I found my question was asked a year ago here app.post() not working with Express but the code written there is outdated (the way bodyparser was added doesn't work anymore as well as function mentioned below) plus the asker never chose an answer so the question was never solved.
Here's my code
const express = require("express");
const db = require("mysql");
const app = express();
const bodyParser = require("body-parser");
const multer = require("multer"); // v1.0.5
const upload = multer(); // for parsing multipart/form-data
const http = require("http");
const path = require("path");
app.set("view engine", "jade");
app.set("views", path.join(__dirname));
console.log("before");
app.listen(8000, () => {
console.log("Server started!");
console.log("within");
});
console.log("after");
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.post("/", function(req, res) {
console.log("hit here in post");
res.render("index.jade", {});
console.log("hit here in post");
res.json({ name: "John" });
res.status(500).json({ error: "message" });
res.end();
});
app.get("/", function(req, res) {
res.render("index.jade", {});
console.log("hit here in get");
console.log(req.body);
});
Here's the output.
before
after
Server started!
within
hit here in get
{}
I even tried to wrap the app sets and uses in app.configure like the asker of the other question to see if that was the issue but that configure function doesn't seem to exist anymore because I got an error about it.
Also I should probably note. My routing here is correct. I haven't made a views subfolder yet so that's why I have it written as it is.
Update
I think I may have spotted the issue but I don't understand why it's occurring. In the network tab of the browser I see that GET is getting 404 error because of a favicon.ico request but I don't understand where that request is coming from. I've seen the serve-favicon npm module to support it but didn't want to added because I never intended to add a favicon image to my server. I don't even understand how that would work.
Reply to last comment by James
What do you mean by I configure the middleware after it has started? Are you referring to the fact that the post method is written after port listening has started? Also if that's the reason why post isn't executing how come the get method executes regardless of that? I'm not holding back any server code aside from code I currently have commented out for the moment but that code I posted is my main index.js file and it's the only file I modified from the standard npm init project. I haven't setup any routes because I don't see the need to do so (even when I add react since my project is simple in concept of communication between reactjs, nodejs and a database "hence my frustration") which is why I'm trying to have get and post only access the root directory.
favicon is automatically requested by the browser. it is the icon used in the browser tab or url address bar
Add this, before app.get():
app.all('/', function(req, res, next) {
console.log({method: req.method, url: req.url});
next();
});
I am looking to capture all of the data from any request (images, fonts, css, js, etc) on my website so that I can capture the file details, specifically the file name and file size. I have found almost an identical question/solution:
Node.js : How to do something on all HTTP requests in Express?
But the solution appears to be deprecated with Express v4. Is there a simple solution to do this? As another approach I have tried the below solution with no luck:
var express = require("express");
var path = require("path");
var port = process.env.PORT || 3000;
var app = express();
var publicPath = path.resolve(__dirname, "public");
app.use(express.static(publicPath));
app.get("/", function(req, res){
// I want to listen to all requests coming from index.html
res.send("index.html");
});
app.all("*", function(){
// can't get requests
})
app.listen(port, function(){
console.log(`server listening on port ${port}`);
});
Also I am not looking to do this from Fiddler/Charles because I am looking to display this data on my site.
Express routes are predicated on order. Notice the answer that you linked in your question has the middleware defined, and used before all other routes.
Secondly you're trying to implement something that requires middleware, not a wildcard route. The pattern in link you provided in your question is not deprecated according to their docs.
app.use(function (req, res, next) {
// do something with the request
req.foo = 'testing'
next(); // MUST call this or the routes will not be hit
});
app.get('/', function(req, res){
if (req.foo === 'testing') {
console.log('works');
}
res.send("index.html");
});
I am hosting a single page app with Node and Express. I use the static middleware for the client. I am using path URLs to navigate the app, for example domain.com/profile/134. I am using history.pushState to change pages internally on the client, and this works fine. What I am missing is a wildcard rule on the server to catch all possible paths when the user accesses my page directly to a path that is not root. If I try to access domain.com/profile/134 directly I get this: "Cannot GET /profile/134". I have tried to insert a wildcard get at the end of server.js, but it seems to be hit every time, also when I access the page root. This is my relevant code:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/../client'));
app.get('/*', function(req, res) {
console.log('wildcard');
});
Is this the correct GET wildcard rule to achieve what I need, and how can I serve the static client inside this handler? My client side will find the right page afterwards as long as the initial path is preserved. I basically want this wildcard rule to behave the same as the static rule, but keep the initial path.
You can use a hack
app.get('/:url', function(req, res) {
console.log('wildcard');
});
or try this one
app.get('/(.*)', function(req, res) {
console.log('wildcard');
});
[edited]: this should work as you expect:
var express = require('express');
var app = express();
app.get(/(.*)/, function(req, res) {
console.log("req.path", req.path);
res.send('success');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
I ended up using an npm module named express-history-fallback-api to solve this. Out of the box it solved both simple and advanced paths, like domain.com/settings and domain.com/profile/username
https://www.npmjs.com/package/express-history-api-fallback
I want to be able to host multiple NodeJS apps under the same domain, without using sub-domains (like google.com/reader instead of images.google.com). The problem is that I'm always typing the first part of the url e.g. "/reader" in Express/NodeJS.
How can I set up an Express app so that the base URL is something.com/myapp?
So instead of:
app.get("/myapp", function (req, res) {
// can be accessed from something.com/myapp
});
I can do:
// Some set-up
app.base = "/myapp"
app.get("/", function (req, res) {
// can still be accessed from something.com/myapp
});
I'd also like to configure Connect's staticProvider to behave the same way (right now it defaults to serving static files to something.com/js or something.com/css instead of something.com/myapp/js)
The express router can handle this since 4.0
http://expressjs.com/en/api.html#router
http://bulkan-evcimen.com/using_express_router_instead_of_express_namespace.html
var express = require('express');
var app = express();
var router = express.Router();
// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
});
// this will only be invoked if the path ends in /bar
router.use('/bar', function(req, res, next) {
// ... maybe some additional /bar logging ...
next();
});
// always invoked
router.use(function(req, res, next) {
res.send('Hello World');
});
app.use('/foo', router);
app.listen(3000);
Previous answer (before express 4.0) :
The express-namespace module (dead now) used to do the trick :
https://github.com/visionmedia/express-namespace
require('express-namespace');
app.namespace('/myapp', function() {
app.get('/', function (req, res) {
// can be accessed from something.com/myapp
});
});
At the moment this is not supported, and it's not easy to add it on your own.
The whole routing stuff is buried deep inside the server code, and as a bonus there's no exposure of the routes them selfs.
I dug through the source and also checked out the latest version of Express and the Connect middleware, but there's still no support for such functionality, you should open a issue either on Connect or Express itself.
Meanwhile...
Patch the thing yourself, here's a quick and easy way with only one line of code changed.
In ~/.local/lib/node/.npm/express/1.0.0/package/lib/express/servers.js, search for:
// Generate the route
this.routes[method](path, fn);
This should be around line 357, replace that with:
// Generate the route
this.routes[method](((self.settings.base || '') + path), fn);
Now just add the setting:
app.set('base', '/myapp');
This works fine with paths that are plain strings, for RegEx support you will have to hack around in the router middleware yourself, better file an issue in that case.
As far as the static provider goes, just add in /mypapp when setting it up.
Update
Made it work with RegExp too:
// replace
this.routes[method](baseRoute(self.settings.base || '', path), fn);
// helper
function baseRoute(base, path) {
if (path instanceof RegExp) {
var exp = RegExp(path).toString().slice(1, -1);
return new RegExp(exp[0] === '^' ? '^' + base + exp.substring(1) : base + exp);
} else {
return (base || '') + path;
}
}
I only tested this with a handful of expressions, so this isn't 100% tested but in theory it should work.
Update 2
Filed an issue with the patch:
https://github.com/visionmedia/express/issues/issue/478
Just to update the thread, now with Express.js v4 you can do it without using express-namespace:
var express = require('express'),
forumRouter = express.Router(),
threadRouter = express.Router(),
app = express();
forumRouter.get('/:id)', function(req, res){
res.send('GET forum ' + req.params.id);
});
forumRouter.get('/:id/edit', function(req, res){
res.send('GET forum ' + req.params.id + ' edit page');
});
forumRouter.delete('/:id', function(req, res){
res.send('DELETE forum ' + req.params.id);
});
app.use('/forum', forumRouter);
threadRouter.get('/:id/thread/:tid', function(req, res){
res.send('GET forum ' + req.params.id + ' thread ' + req.params.tid);
});
forumRouter.use('/', threadRouter);
app.listen(app.get("port") || 3000);
Cheers!
I was able to achieve this using a combination of express-namespace for the routes and a fix from the below google group discussion for the static assets. This snippet will treat a request to /foo/javascripts/jquery.js like a request to /javascripts/jquery.js:
app.use('/foo', express.static(__dirname + '/public'));
Source:
https://groups.google.com/forum/#!msg/express-js/xlP6_DX6he0/6OTY4hwfV-0J
I know this is a very old question but Express has changed a lot since most these answers were posted so I thought I'd share my approach.
You can, of course, use Routers with Express 4 to group together related functionality behind a particular path. This is well documented and has already been covered by other answers.
However, it is also possible to mount an entire application at a particular path. As an example, let's assume our application (the one we want to host at /myapp) looks like this, in a file called myapp.js:
var express = require('express'),
path = require('path'),
app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.get('/hello', function(req, res) {
res.send('Hello');
});
// Lots of other stuff here
exports.app = app;
In our main js file we could then mount this whole application at the path /myapp:
var express = require('express'),
app = express(),
myApp = require('./myapp').app;
app.use('/myapp', myApp);
app.listen(3000);
Note that we've created two applications here, one mounted on the other. The main application could have further sub-apps mounted at different paths as required.
The code in myapp.js is completely independent of where it was mounted. It's similar to the structure used by the express-generator in that regard.
Some documentation about sub-apps can be found here:
https://expressjs.com/en/4x/api.html#app.mountpath
https://expressjs.com/en/4x/api.html#app.onmount
There are also reliability issues. If reliability is important, a common solution is to use a front-end reverse HTTP proxy such as nginx or HAProxy. They both use single-thread evented architecture and are thus very scalable.
Then you can have different node processes for different subsites, and if one site fails (uncaught exception, memory leak, programmer error, whatever) the rest of sub-sites continue to work.
I was looking for this feature but for API routes, not for static files. What I did was that when I initialized the router, I added the mount path. So my configuration looks like this
//Default configuration
app.configure(function(){
app.use(express.compress());
app.use(express.logger('dev'));
app.set('json spaces',0);
app.use(express.limit('2mb'));
app.use(express.bodyParser());
app.use('/api', app.router); // <---
app.use(function(err, req, res, callback){
res.json(err.code, {});
});
});
Notice the '/api' when calling the router