Express.js and Angular.js html5mode (Avoiding # in url) - javascript

I have been working on avoiding # in Angular app with ExpressJS serverside.
I have researched how to enable html5mode and it worked great. But whenever there is another 'get' request to retrieve data from another url such as /api/services, it seems like somehow broken and do not provide data properly to the page.
Here's what I have done in express end.
router.get('/*', function (req, res, next) {
res.render('index');
});
router.get('/api/service-edit', function (req, res, next) {
Service.find(function (err, services) {
if (err) {return next(err);}
res.json(services);
});
});
I am not 100% sure, but what I guess is '/*' causes a problem for the server in reading api urls.
I am wondering if any of you have an experience in this problem and a solution to figure this out.
Thank you for your time.

In expressjs the routing rules are matched in the order you present them in the code. So the '/*' rule is always matched first and the second rule is never reached.
Putting the second rule before the first one will probably solve the problem.
Hope it helps.

Related

How to disable access to certain parts of an express server but be able to enable it later

I have a server that is fully functioning, but I only want it to be accessable when I say. I do this via a discord bot which works fine. I currently have a boolean variable server_on and an if (server on) { do } in all of my app.get and app.post functions. Is there a cleaner way to do this, or is this if statement in every function the only way?
Edit:
Final working code
var block_server_middleware = function (req, res, next) {
if (!server_on) { res.send("server is currently unavailable") }
else { next() }
}
app.use(block_server_middleware)
and the other app.get and app.post functions were not changed at all
This was the only few lines added that made the whole idea work
You can define one middleware function that goes before all your routes are defined:
app.use((req, res, next) => {
if (!server_on) {
// stop all routing
res.send("server not on!");
} else {
// let routing continue
next();
}
});
This will keep your routes from ever getting run until server_on is back to true. If you have any routes you want to leave open all the time, then just place them before this middleware.
You can replace res.send("server not on!"); with whatever is appropriate for your use. You can return a single web page or you can send back a 4xx or 5xx error status (perhaps a 503 error).

Express middleware gets called multiple times

My middlewares are getting called multiple times and I can't figure out why.
It's a really short code and it is very frustrating as I just started learning express and node.
I don't understand why it's even getting into the second middleware, I didn't use next(), I used res.send().
I am taking an online course and it's the same code as it is described. I also searched stackoverflow but nothing helped.
I did read something about the favicon that calls it a second time, but I can't figure out why this is getting called multiple times.
const express = require("express");
const app = express();
app.use("/", (req, res, next) => {
console.log("This always runs!");
next();
});
app.use("/add-product", (req, res, next) => {
console.log("In first middleware!");
res.send("<h1>Add Product</h1>");
});
app.use("/", (req, res, next) => {
console.log("In second middleware!");
res.send("<h1>Hello from express!</h1>");
});
app.listen(3000);
If I'm opening localhost:3000/add-product I should get in the console:
This always runs!
In first middleware!
but I actually get:
This always runs!
In first middleware!
This always runs!
In second middleware!
This always runs!
In first middleware!
Could it be that the favicon automatically executes all middlewares once? I added this code before the first app.use() call:
app.get("/favicon.ico", (req, res) => res.status(204));
Now I get
This always runs!
In first middleware!
This always runs!
In first Middleware!
I still get it twice.
edit edit edit:
This appears only to happen in chrome.
Don't use app.use for routes that's mainly used for middleware registration you want to use the router. https://expressjs.com/en/4x/api.html#app.use
app.(post|get|delete|put)("route", function(req,res,next){})
in your case it's best to see if your browser is requesting 2 http calls. If so it'll double up.
The browser is sending a request for a favicon. Press F12 on chrome and you will see two requests being made. One of them will be local host and other one will be favicon.ico. Therefore you are seeing two sets of console.log() being printed out to the console.
Instead of reinstalling chrome you could just right click on favicon.ico and click on Block request URL to stop the browser from sending requests for favicon.ico
Was having the same kind of problem but I didn't find any solution online, but I think I found the solution for this. The reason the middleware is being run more than once is that the client is making a request to the server more than once and each of those requests needs to go through the middleware each time.
For example, the first request is the route request itself, then the second one is the request for stuff in public such as images, CSS files, and more. So 2 requests are being made and that means the middleware will be run twice.
My code solution for this is just to have an if statement that checks whether the middleware req.originalUrl contains the file or folder name that is in public, if it doesn't contain it then the middleware code would then be run.
function middleware(req, res, next) {
const condition = !req.originalUrl.includes("css") && !req.originalUrl.includes("image")
if (condition) {
// middleware code
} else if (!condition) {
next()
}
}
I would only suggest you to do this only if you are making a middleware such as a page counter, or a middleware that is only needed to be run once per route request
Problem solved: I reinstalled Chrome and it works fine now. Thanks all!

URL rewriting not working in Express 4.14.1

I've found in quite a few SO posts that in order to rewrite a URL in Express 4 I would do something like the following:
router.use('/one/:someId', (req, res, next) => {
req.url = `/two/${req.params.someId}`;
next();
});
router.get('/one/:someId', (req, res) => {
res.send("reached /one/:someId");
});
router.get('/two/:someId', (req, res) => {
res.send("reached /two/:someId");
});
But when I try this, not only does the URL does not change to my expected "/two/some integer" and stays being "/one/some integer" but it gets to the 404 - Not Found page I have set up in my app file.
This routes are in a router file and I have also tried setting the URL to:
req.url = `/routerPath/two/${req.params.someId}`;
but the result is exactly the same.
So what could I be missing?
Thank you.
You have to distinguish two kinds of redirects:
Internal redirects work on the server, without the client noticing. They are a convenience for your server programming and never necessary - you could always introduce a helper method that gets called by all endpoints.
HTTP redirects advise the client (e.g. a web browser) to go to a different URL. Since you expect the URL to change, that's the one you want.
Simply call res.redirect, making sure to encode special characters:
router.get('/one/:someId', (req, res) => {
res.redirect(`/two/${encodeURIComponent(req.params.someId)}`);
});
router.get('/two/:someId', (req, res) => {
res.render("reached /two/:someId");
});

req.url always gives me "/" no matter what path I use

//Force HTTPS
if (app.get('env') == 'production'){
app.use('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https') res.redirect(301, "https://" + req.host + req.url)
/* x-forwarded-proto is used because heroku */
else next()
})
}
Edit: for anyone using this example -- req.host is deprecated, be sure to use req.hostname instead.
I have a block of code that redirects any http request to the same page, but with https protocol.. it works beautifully except that making an http request always redirects to the homepage. I've traced it down to the fact that req.url is always equal to '/' no matter what the request url actually is.
i.e. If I navigate to page http://hostname.com/my/path I would expect req.urlon the server to equal "my/path/" but instead it just equals "/".
I'm thinking this has something to do with either react-router, which I'm using for the front-end, or the way that heroku internally redirects the request, but I have not been able to find a solution yet.
Mounting a function to a path with app.use() rewrites the req.url by removing the mount point part from it. You should use req.originalUrl instead or omit the path argument:
app.use(function (req, res, next) {
// req.url not changed as path is not specified
});
app.use('/foobar', function (req, res, next) {
// foobar removed from the req.url
});
app.use('*', function (req, res, next) {
// everything (*) removed from the req.url
// original URL available in req.originalUrl
});
Is app.use express or something? My guess would be that youre probably performing a redirect before you get to that snippet of code you provided. It's probably not react-router because front-end stuff happens after the backend returns a response (meaning req.url shouldnt be affected by react-router because react-router comes later)

How do I call a invoke an ajax get request from client side, using Node/Express?

I have a file shuffleRoute.js where I define this:
router.get("/shuffle?jokers=false", function (req, res) {
cards['a','b','c'];
let shuffledCards = _.shuffle(cards);
res.status(200).send(shuffledCards);
});
I have an index.js where I define:
app.get("/v1/game", require("./routes/shuffleRoute.js"));
I have a game.html where onload I need to do an ajax request to get the shuffled cards. How do I do that?
doing this
$.get( "/v1/game", function(res) {
console.log(res);
});
does not work.
I am getting this error:
jquery-2.2.4.min.js:4 GET localhost:8080/v1/game 500 (Internal Server Error) –
I was using morgan to log things in the server which was incorrectly done.
However, commenting that out gives me this error.
jquery-2.2.4.min.js:4 GET http://localhost:8080/v1/game 404 (Not Found)
May be wrong but i see routes problem here.
When you define routes for express use app.use
var myRoute = require('PathToYourRouteFile');
app.use("/v1/game", myRoute);
In route file. Im asuming you use express router you need to define something like this
youRuoterName.get('/', function(req, res, next) { })
This request will be succes when you go to localhost/v1/game.
If you want another one just do
youRuoterName.get('/shuffle', function(req, res, next) { })
Which will be succes when you go to /v1/game/shuffle.
In your example i see only one route /v1/game/shuffle which clearly not match /v1/game and im not even sure that rest of code works as expected.
So please read docs carefuly http://expressjs.com/en/4x/api.html#router.route
and all should work.
Hope this helps.

Categories

Resources