Express routing gives 404 for url's apart from localhost - javascript

My application currently serves fine making calls with Express, but I have a page now rendered by:
app.get('/user/:username', function(req, res){
serve html page (no problems)
}
and from that page, I'm making a request for
return $http.get('/api/user/:s').success(function (resp) {
stuff...
}
which is returning a 404 not found.
The call is in my Express app.js as
app.get('/api/user/:username', routes.api.getDBUser);
and I've been stumped on this problem for ages now. I feel like the issue is from something related to the URL.
EDIT:
app.use("/user", express.static(path.join(__dirname, 'static'))); //serving statics for localhost/user paths
app.get('/api/user', authentication.isAuthenticated, routes.api.getUser);
app.get('/api/users/:username', routes.api.getDBUser);
app.get('/api/user/friends', authentication.isAuthenticated, routes.api.getUserFriends);
app.get('/api/user/history', authentication.isAuthenticated, routes.api.getUserGameHistory);
is all the routes related to the user here. I'm not sure if this has something to do with it, but accessing a routing call when the url is something like localhost(port)/something, it's okay. The URL at this particular page I'm trying to make the call from is localhost(port)/user/something

Related

Server Side Routing vs. Front End Routing with Proxy

I hope my question doesn't come off as silly. I have quite a bit of experience on the front end but very little on the back end.
I have a React application which uses Node.js and Express on the back-end. I have declared "proxy": "http://localhost:3001" in my package.json which I am not 100% what this does but I know it is helping to connect my server (which runs on port 3001).
The issue I am having came about while setting up Auth0 on my backend to verify users. The first thing I noticed was that I was not able to run a get request to http://localhost:3001/login instead I had to navigate the user to the url http://localhost:3001/login. I'm not sure why this is but I assume it has something to do with Auth0 settings.
After I login Auth0 returns users to a callback url. Auth0's docs recommend using localhost:3000/callback since there docs also have a backend endpoint at /callback. However after logging in the user just gets routed to an empty page at http://localhost:3000/callback and the backend endpoint is never hit. I found that strange since I was basically copying and pasting from the Auth0 guide to setting up a login with Express.
Anyway I found that if I changed the callback url to my server at http://localhost:3001/callback than the server side code runs. This makes sense other than the Auth0 docs saying to use port 3000. It seems like maybe my proxy should be linking these somehow.
The callback endpoint function looks like this:
router.get('/callback', function (req, res, next) {
console.log('called')
passport.authenticate('auth0', function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/login');
}
req.logIn(user, function (err) {
if (err) {
return next(err);
}
const returnTo = req.session.returnTo;
delete req.session.returnTo;
res.redirect(returnTo || '/user');
});
})(req, res, next);
});
When this runs successfully it should route the user to my Users page at localhost:3000/users however because I changed the callback route to 'localhost:3001/callbackthe callback endpoint is routing me tolocalhost:3001/users`.
I can kind of see what is going on. When I go to a url using 3001 I am hitting my endpoints. When I go to a url using 3000 I am viewing my front end pages. I just don't understand why the Auth0 docs would tell me to use my front end port for the callback?
I'll try to help but I'm not sure this is the answer.
If you set in your package.json the proxy to "proxy": "http://localhost:3001" then in your app to make a request you don't need to use the full URL,
axios.get('/login').then(res=>res.data).catch(err=>console.log(err));
For example without the proxy setted
axios.get('http://localhost:3001/login').then(res=>res.data).catch(err=>console.log(err));
In Auth0 the host URL and port is not a problem, U can use whatever U want, the point is the /callback route, in Auth0 you can configure a custom route for the callback but by default in your app, you need to have a route /callback. remember to add localhost:3001 to Auth0 configurations
I hope to help.

Angular only works if I specify app.get("*"[...]); in my server.js

I just startet developing with server side JavaScript and this is my first project with it.
It is a command and control server for my owncloud server running with angular, Expressjs and bootstrap. At the moment I got trouble adding the functionality for the stop server button.
It should some code to log into the the server via ssh and do all the necessary stuff to shut it down gracefully.
The problem is, that I really can't (and also don't want to) add this via a browser script since I want to use an ssh library. Running a server side script by pressing a button doesn't seem to be possible at all (please tell me how if it is anyway, that would be the solution to all of my problems :)).
So I thought I could redirect the user to the /on page as he clicks the button and perform the actions in the app.get callback function. And here is the problem: In my server.js (the main node server) I have "two" endpoints defined at the moment
app.get("*", (req, res) =>{
res.sendFile(path.join(__dirname, "src/index.html"));
});
and
app.get("/on", (req, res) =>{
console.log("redirecting...");
//DO SOMETHING
res.redirect("/");
});
In the second one I would like to perform the ssh actions.
But as I change the first code block to (notice the / instead of the *)
app.get("/", (req, res) =>{
res.sendFile(path.join(__dirname, "src/index.html"));
});
The whole app doesn't seem to have angular any more. All angular components do show up but they are just empty and not filled with the content I defined in the app.component.html. Why is this occurring and how can I fix this? Thank you for any help ;)
PS: you can find all the code at: GitHub
There are multiple things you would preferably do, but to keep the answer short, you need few changes so you can have this up and running, first, app.get("*", ...) redirects every get to that code block, so you need to do this:
//Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//Angular DIST output folder
app.use(express.static(path.join(__dirname, "dist")));
app.get("/", (req, res) =>{
res.sendFile(path.join(__dirname, "dist/index.html"));
});
app.get("/on", (req, res) =>{
console.log("redirecting...");
//DO SOMETHING
res.redirect("/");
});
Notice one change, you don't want to call the src/index, you want to build the angular to dist folder and use that index.html, second, the route "/" will redirect to home page, the "/on" will now enter the the desired endpoint. If this is pretty much everything you want to do with the endpoints, i guess this is fine, but if you want to build something more complex, i would abstract things out. hope this helps, cheers.

Use the same Node Script for Multiple Requests

I am using express js to build a small REST framework. in the app.js, I am forwarding to a separate script search.js, where I will send a json object (array) as the response to the requestor. for this, I am using the following code in the search.js.
router.get('/', function(req, res, next) {
//some search action
res.json(searchresult);
}
And my app.js looks like this.
app.use('/search',search)//use the search.js script
This works well for the first request. But when I reload the home page and resend a request, I get the following error.
Error: Can't set headers after they are sent.
So far, I've tried using res.write(JSON.stringify(search_result));. But this would not send the data correctly and I would get an error in the front end saying net::ERR_INCOMPLETE_CHUNKED_ENCODING.
What am I doing wrong? How can I make this work?

Node.js: Changes on route settings don't show effect

For some strange reason, some changes on my route settings (MEAN environment, Node v0.12.2 and express 4) don't show effect any more!? Particularly instructions where I respond to client requests using ".sendfile()".
app.get('/', function(req, res){
res.sendfile("/public/index.html"); // <-- trying to exclude or change this
console.log("debug message"); //added later, never shown!!
});
Excluding or altering the sendfile instruction in the example above doesn't change anything - index.html is alyways being delivered upon request. Not even simple debug messages like console.log are shown any more?! Here's what I checked:
restarted Node.js server and computer several times
checked for duplicates of routes.js file
checked for duplicates of home route ("/")
cleaned browser cache
even deleted the ENTIRE route, site still delivered upon request!?!?
Maybe there is some kind of server-side cache that needs to be wiped?! I got no idea any more of what's wrong. Suggestions anyone?
There are changes in express 4 with respect to express 3. In express 4 we have got a new method app.route() to create chainable route handlers for a route path and a new class express.Router to create modular mountable route handlers. For more details ref: Moving to Express 4 What you can do is try using code in following order:
app.route('/')
.get(function(req, res) {
res.render('index');
});
And its also good serve static files by adding:
app.use(express.static(path.join(__dirname, '../public')));
Good luck...:)

Understanding Express routing in conjunction with AngularJS (using mean.js boilerplate)

I am developing a web application with the mean.js boilerplate code. Recently I added a view to my application (the 'analysis' page) by creating an analysis module and added some route logic with the following code.
//Setting up route
angular.module('analysis').config(['$stateProvider',
function($stateProvider) {
// Projects state routing
$stateProvider.
state('imageAnalysis', {
url: '/image_analysis',
templateUrl: 'modules/analysis/views/tools.client.view.html'
});
}
]);
This works just dandy, I can go to homepage.com/image_analysis and see my tools.client.view.html page. My goal now is to have this page only visible to user who are logged in. My first approach to this was to check if the user was logged in the angular routes logic, this has proven to be difficult for me. I also read that check authentication in the front end is very unsafe. So I've decided to check if the user is logged in with Express routing.
Here is an example of what Express routing looks like for one of my other AngularJS modules
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
var projects = require('../../app/controllers/projects.server.controller');
// Projects Routes
app.route('/projects')
.get(users.requiresLogin, projects.list)
.post(users.requiresLogin, projects.create);
app.route('/projects/:projectId')
.get(users.requiresLogin, projects.read)
.put(users.requiresLogin, projects.hasAuthorization, projects.update)
.delete(users.requiresLogin, projects.hasAuthorization, projects.delete);
// Finish by binding the Project middleware
app.param('projectId', projects.projectByID);
};
Notice the users.requiresLogin function which check if a user is logged in and redirects the user to the signin page if they are not. I want to take advantage of this function. Some things I dont quite understand in the boilerplate code are what is the purpose of app.route()? I think this might be a middleware but I am not sure what it does.
Here are some attempts I've take taken at messing around with express routing. These attempts are in my analysis.server.routes.js file that I created.
Attempt 1
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
// analysis routes
app.get('/image_analysis', function(req, res) {
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
});
};
I thought this would log 'helloworld' when I access the image_analysis page, but it didnt appear to do anything.
Attempt 2
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
// analysis routes
app.route('/image_analysis')
.get(users.requiresLogin);
};
Based on the other code, I thought this might work to require login for the analysis page. But it did nothing.
Any help would be much appreciated! Thanks everyone, I am struggling to grasp express routing at the moment and stackoverflow has been a tremendous help.
I don't have a solution, or not at least at this moment that I could think of.
However I can explain to you how things work and why a solution might not be trivial.
what is the purpose of app.route()
This defines your routes.
app.route('/projects/:projectId')
.get(users.requiresLogin, projects.read)
.put(users.requiresLogin, projects.hasAuthorization, projects.update)
.delete(users.requiresLogin, projects.hasAuthorization, projects.delete);
What that code does is when a client requests a URL like one of the following
GET /projects/5562ff08de4f70180bba3083
PUT /projects/5562ff08de4f70180bba3083
DELETE /projects/5562ff08de4f70180bba3083
it first executes that middleware function users.requiresLogin,
which is defined to be common in all methods (.get .put .delete)
and then their respective middlewares in that order
projects.read | projects.hasAuthorization ...
On how Angluar routing works in contrast to Express routing:
Angluar routing is all done client-side. It's all achieved through Javascript
changing the addressbar url and displaying the view attached to that route.
Your Angular app is served by the server through a single (Express) route - / (homepage)
So again, your entire Angular app loads thorough just 1 route on the server-side,
and then Angular takes over the routing to client-side through it's own ui-router.
Now it must be starting to seem obvious that it's not trivial to have server-side authentication check
interfere between client-side routing.
You can only have server-side authentication work with routes that server actually is in control of serving.
Those are mostly just your API routes, in your case.
Attempt 1
app.get('/image_analysis', function(req, res) {
console.log('helloworld');
I thought this would log 'helloworld' when I access the image_analysis page, but it didnt appear to do anything.
It indeed should have! Unless.. there's a route that comes before it that already serves all requests
app.get('*', function(req, res) {
res.send(angularApp); // your angular app is served here
});
// No request would *need* to go beyond past this point
// because it already got served above
app.get('/image_analysis', function(req, res) {
// so this isn't reached.
console.log('helloworld');
});
So that's why it doesn't work.

Categories

Resources