URI bind Express.js - node.js

Hello I want to bind the URI of my app, for example lets imagine this scenario.
I am running express app on port 3000,
nginx on port 80, proxying requests of URI api to port 3000
And have this route on express
// Home
app.get('/', function(req, res) {
res.send('Hello!');
});
If I try access from localhost:3000 I get Hello! in my browser (that's expected),
but if I try to access from localhost/api I will get an error, of course he can't find the route I'm tryng to access.
If I change app.get to app.get('/api/... it works as expected, but this isn't what I want... I would need to prepend api in every route, there must be another way to do this, something like:
URI binding
URI filter ??
I read the documentation but can't find anything to solve my problem, and I'm thinking of doing a package that does URI bindings on express to solve this problem.

See my answer here for a solution that lets you point every request matching a leading /api to a particular express app. In the linked case, the user wanted to do some things without the leading fragment. You could leave out the app.use(app.router) for the main express app since you only care about the /api/ routes.
<snip>
var http = require('http');
var express = require('express');
var desktopApp = express();
var mobileApp = require('./mobile.js');
desktopApp.use('/mobile', mobileApp)
desktopApp.use(desktopApp.router);
</snip>
Also I am pretty sure that you can actually rewrite request.url yourself. I have never tried this so I can't promise it works! see docs http://expressjs.com/4x/api.html#req.originalUrl Also be sure to put this at the very top of your routing functions, so it is executed before any subsequent routes.
app.all('*', function(req, res, next){
req.url = req.url.replace(/^\/api/, '');
//the regex replaces leading /api with empty string
//req.originalUrl will keep the old url
next();
});

Related

Node/Express Server on DigitalOcean only responding with "/" route even if I hit "/test" route

I'm trying to host a Node.js/Express server for the first time, and I'm currently attempting to use Digital Ocean's App Platform. I have it up and running, but my routes aren't working correctly. Digital Ocean allows me to set HTTP Request Routes, and I have "/" and "/test" set for two of them. No matter what route I hit, it only ever responds with the "/" route.
Here is my code for reference:
require("dotenv").config();
const { SERVER_PORT } = process.env;
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.json());
app.get("/", (req, res) => {
res.status(200).send("This is the / route")
})
app.get("/test", (req, res) => {
res.status(200).send("This the /test route");
})
app.listen(SERVER_PORT, () => {
console.log(`Server running on port ${SERVER_PORT}`);
});
When I make a GET request to "https://{DigitalOceanURL}/", I get the correct response of "This is the / route", however when I make a GET request to "https://{DigitalOceanURL}/test", I still get the response of "This is the / route" and not "This the /test route" as is in my code.
If I try and make request to a route that doesn't exist, however, such as "https://{DigitalOceanURL}/doesntexist" I get the response "Cannot GET /doesntexist". To me this suggests that the routes I'm entering into DigitalOcean are registering, but for some reason it's not seeing anything past the initial "/" in the route.
I've been trying to Google for a while now and I can't seem to diagnose what's wrong. I thought it might be something with app.use vs app.get, as on this answer on a SO post it says that app.use "...will match all requests beginning with..." your route, whereas app.get "...matches only GET request with exact match.". So it seems that, since I'm hitting the exact route, it should be working? But it feels like the general area of my problem, as it seems to only be registering the "/" in the route and nothing else?
Both the endpoints work when running the server on localhost, so it seems like there must be some disconnect with DigitalOcean.
Any help would be greatly appreciated - as I mentioned this is my first time trying to host and it's a bit overwhelming.
Thank you!
The issue was with my Digital Ocean settings. As I said in my question: "Digital Ocean allows me to set HTTP Request Routes, and I have "/" and "/test" set for two of them." It worked when I removed the "/test" route and only had one, "/" in my Digital Ocean settings. I interpreted it as "List all routes I had in my express app", but I guess that's not what it meant. There only should've been one set: "/".
Your / route declaration comes before the one for /test. Express matches in code order, so / picks up every incoming request, and none make it to the more specific route. Switch their order.
This isn't specific to Digital Ocean, of course.

How to get url of a page that makes a http ajax GET request in node.js?

In node.js I have a site that serves pages from the same server. Pages can request for files on the same server using http get with ajax. However some pages are not allowed to request a file from a certain path. How can I validate this in node.js?
Also this should be in a way a user can't hack from client side. The node.js would need a way to see if the request came from a page from a certain url and if so then block it if the link it requests is in a specified folder.
Thanks
Assuming you've setup your server like so:
var http = require('http');
server = http.createServer(function(req, res)
{
...
you can get the referring URL by accessing req.headers.referer
Then you'll need to check this either with a regular expression (if the allowed URLs match a pattern) or against an array of acceptable values.
UPDATE
Next, you could keep an array of valid visited URLs in a session and then check if the acceptable referring URL is actually in this list (and thus not necessarily spoofed).
In any node function , we have access to request and response object. Consider the following eg :
var express = require('express');
var router = express.Router();
var app = express();
app.get('/', function(request, response){
var urlPath = request.path;
response.send("Hello");
});
app.listen(3000);

two node.js servers at one web address

I have two web application node.js servers and I need to have them under one web address.
It should work like this:
example.com/wa/* -> redirect to example.com:pppp
others example.com/* -> redirect to example.com:qqqq
I have experimented with http proxy module, but it doesn't work, maybe the problematic part is the fact, both servers are https not http.
Using Express you can do something like this
var express = require('express');
var http = require('http');
var app = express();
app.use('/wa/*', function(req, res){
req.redirect('example.com:pppp')
});
app.use('/*', function(req, res){
req.redirect('example.com:qqqq')
});
http.createServer(app);
Not tested, but it should work.
Note: The /wa/* route must come before the /* route. otherwise all requests will get redirected by the first middleware

Nodejs Express keeps serving the same file to all requests

So i have an express app and in the app.js i have this:
app.use('/index', function (req, res, next){
res.sendFile(__dirname+'/index.html');
}
app.get('/script.js',function(req,res){
res.sendFile(__dirname+'/public/script.js');
and after starting the server and type localhost:3000/index and the app works fine but here comes the problem..
when i change the first app.use() function to:
app.use('/', function (req, res, next){}
so that i don't have to type the index part in the URL, all the next get requests respond with index.html page and i tried adding
res.end(); after res.sendFile();
but no other response gets sent after that, how can i solve?
Your / route is acting as a wildcard and capturing all requests, which means that anything not matching a route defined BEFORE this route will be caught by it. You have two options here:
Change app.use to app.get so that you are explicitly only matching / (and only with a GET method)
Move the route to the bottom of all of your routes
As explained on the Express.js API docs for app.use here:
A route will match any path, which follows its path immediately with a “/”. For example: app.use('/apple', ...) will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.

Is it possible to render another express application from express?

Basically what happened was we have an app server that is running express and routes to a bunch of SPAs. This was great but then we wanted to have an app that runs its own node/express script (ghost). I can't figure out how to set the route /ghost to go to ./webapps/ghost/index.js
Is this just not possible?
You need to redirect incoming requests to the ghost express instance. I have done so in my personal site by adding a /blog route to my primary express instance and forwarding any request to it to the ghost expresss instance. Check it out here: https://github.com/evanshortiss/evanshortiss.com/blob/master/server.js
The basic gist is that you do the following:
app.use('/blog', function(req, res, next) {
// Forward this request on...
return next();
}, ghostServer.rootApp); //...but we forward it to a different express instance
If you're running both as separate processes then you could use Apache or nginx to just redirect the requests. If you absolutely must use an express application to forward requests then try the node-http-proxy module.
If you need to proxy from express you could do this using the http-proxy module by Nodejitsu:
var proxy = require('http-proxy').createProxyServer({});
app.use('/blog', function (req, res) {
// You may need to edit req.url (or similar) to strip the /blog part of the url or ghost might not recognise it
proxy.web(req, res, {
target: 'http://127.0.0.1:'+GHOST_PORT
});
});

Resources