Node Express sendFile requiring ending slash - node.js

I'm using the following get:
app.get("/:project/*", auth, function (req, res) {
Then parsing against a config file to load a directory dynamically:
var path = req.params[0] ? req.params[0] : "index.html";
res.sendfile( path, { root: "./builds/" + config[req.params.project].dir + "/dist/" } );
Which works great, only problem is that it requires my urls to end with a "/" if I'm going to the default (index.html). For example, I have to use http://server.com/some_project/ and if the trailing slash isn't there it throws a Cannot GET /some_project error. Curious if there's a way around this?

app.get("/:project/?*", ...)
Add the question mark. That should allow you to do with or without the trailing slash.

Related

Google cloud functions replaces double slash in url

Im trying to deploy cors-anywhere on Google Cloud Functions. Im supposed to provide the url after gcp's link.
It looks like this :
https://us-central1-my-project.cloudfunctions.net/my-function/http://dummy.restapiexample.com/api/v1/employees
but it's transformed to :
https://us-central1-my-project.cloudfunctions.net/my-function/http:/dummy.restapiexample.com/api/v1/employees
All the double slashes after the host are transformed to simple ones.
I tried replacing req.url to transform http:/ to http:// but still wont work. Maybe this needs to be fixed in the webserver level.
Here's my function in GCP
var cors_proxy = require('cors-anywhere').createServer({
requireHeader: ['origin', 'x-requested-with'],
removeHeaders: [
'cookie',
'cookie2',
],
// See README.md for other options
});
exports.myFunction = (req, res) => {
req.url = req.url.replace('/my-function/', '/'); // Strip '/my-function' from the front of the URL, else the proxy won't work.
return cors_proxy.emit('request', req, res);
};
Anyone tried to deploy this in a serverless function?
You're using req.url which contains a normalized version of the request URL. You'll want to use req.originalUrl which, as the name suggests, retains the original requested URL. See Express docs for more info.

Express - Allowing for a closing / at the end of a routing path

While routing in Express is quite straightforward I'm having trouble adjusting it to paths that end with a /.
For example, suggest I define the following route:
app.get('/about', (req,res) => res.render('about'));
Now if someone navigates to www.example.com/about the about view is rendered. However, if that same person navigates to www.example.com/about/ the route I specified above will not work. Some people (me included) have gotten used to naturally adding a closing / at the end of paths. I read the Express routing documentation page but it seems the developers were oblivious to this possibility. The only solution I've found thus far is to use regular expressions for each and every route to account for this variation. For example, the route above would become:
app.get(/\/about\/?/, (req,res) => res.render('about'));
Is there a more elegant (or built in) solution to allow for path with a closing / in Express?
This question has already been answered in https://stackoverflow.com/a/15773824/515774
Basically, you will need to add a middleware which will strip the trailing slash and make a redirect request, which will solve your problem.
Following is the code snippet from the previous answer.
app.use(function(req, res, next) {
if (req.path.substr(-1) == '/' && req.path.length > 1) {
var query = req.url.slice(req.path.length);
res.redirect(301, req.path.slice(0, -1) + query);
} else {
next();
}
});
To avoid redirect, you can just rewrite the URL. Reference https://stackoverflow.com/a/13446128/515774
Note: The browser URL stays the same using this approach.
app.use(function(req, res, next) {
if (req.url.slice(-1) === '/') {
req.url = req.url.slice(0, -1);
}
next();
});

Relative paths to another relative path

I have a Node/Express server set up, and we are making the transition from subdirectories to sub domains for localisation, e.g.
es.example.com // old way
www.example.com/es // new way
Doing this for a variety of reasons, but mostly to facilitate the preservation of JWT login state across the internationalised content.
I have run into the problem of links generated dynamically - how to ensure they will preserve the subdirectory?
For example, if I am linking a user from index.html to /user-profile/1000, how can I maintain /es/user-profile/1000? Is there a way of having relative paths to other relative paths? If that even makes sense?
You can use a middleware solution that redirects to the original paths. Here's a rudimentary example
var languages = ['en', 'es'], _ = require('lodash');
app.use("/:lang/*", function(req, res, next) {
console.log(req.params, req.path);
var found = _.find(languages, function(v) {
return v === req.params.lang;
});
if (!!found) {
res.redirect('/' + req.params[0]);
} else {
next();
}
});
This will check for all valid languages and if it recognizes one, it will strip the language from the path and redirect to the original path minus language. Otherwise it will continue to the path provided.

Rewriting path with http-proxy-middleware

Trying to rewrite path of request with http-proxy-middleware. But trouble is that when i am writing such code:
proxyMiddleware('/service/api', {target: 'http://192.168.70.99:8078/'});
It means that path like /service/api/export/1 will be redirected to http://192.168.70.99:8078/service/api/export/1; But I need to redirect it to http://192.168.70.99:8078/export/1. How can I do that?
You can pass the pathRewrite opiton and inside it use regex pattern to remove the path that you don't need:
proxyMiddleware('/service/api', {
target: 'http://192.168.70.99:8078/',
pathRewrite: {
'^/service/api':'' //remove /service/api
}
});

sendFile absolute path

On Windows machine, I have a mapped share folder => Z:/uploads/
using express, I use res.senFile to return a file to the browser:
var download = config.file_dir + "/" + file;
res.sendFile(download);
download value is Z:/uploads/737237213791239.pdf
I get this error:
throw new TypeError('path must be absolute or specify root to res.sendFile
Am I giving a absolute path?
I hit the same issue. I found it easiest to configure my folder with forward slashes, the use path.join to send. This should work work a drive letter or UNC path.
var path = require("path");
config.file_dir = "z:/folder";
//use forward slashes for UNC if you wish to use that instead ie //server/share
var file = path.join(config.file_dir, urlPath);
res.sendFile(file, (err) => {
if (err) {
res.status(err.status || 500).send();
}
});

Resources