Express route regex exception - javascript

i know this is probably a silly question but I cant make it work, Im trying got match any route that does not match a word, api for example (exclude /api/*) but I cant make it work:
'/^(?=\/).(?!api\/).*$'
That doesn't work, then I tried this site: http://forbeslindesay.github.io/express-route-tester/ just to test I match / and give me this code:
/^\/?$/i
Then I tried at express but it didn't match /
Cannot GET /
Then I'm guessing theres something wrong with the code and not with the regex, do you have some hint?
app.get('/^\/?$/i', function(req, res) {

Using regex here doesn't seem like the right approach, it seems more like you'd want to use a parameterized route to handle protected routes.
app.get('/:directory/:page', function(req, res, next){
if(req.params.directory.toLowerCase() == 'api') res.redirect('/') //or whatever you want it to do
else {
//whatever your default action is
}
}
If you wanted to exclude several and handle them in the same way, you could make your if statement use regex:
if(/^(api|other_directory|whatever_else)$/i.test(req.params.directory)) res.redirect('/')

Related

Extract the common query path from RESTFUL URL (Ablate the resources) JS

I have a RESTFUL url design like this: GET /street/:streetName/house/:houseNumber or GET /street/:streetName/house/listings. As you can see, the :streetName and :houseNumber are resource names. I am trying to extract the static (common) parts from the url for some following logics which means I want to get /street/house and /street/house/listings (ablate all resources parts in the url).
I was trying to find a JS lib for this but didn't find one. Any pointers?
PS: I can do some string matching to achieve this like split by "/" then concat them and only care about the key words, so I can ignore all resource names. But this doesn't seem robust.
Assuming you have a route for each URL pattern, you can set an additional property req.staticParts in each middleware:
app.get("/street/:streetName/house/:houseNumber", function(req, res, next) {
req.staticParts = "/street/house";
...
})
...
.get("/street/:streetName/house/:houseNumber/listings", function(req, res, next) {
req.staticParts = "/street/house/listings";
...
})
.use(function(req, res) {
additionalLogic(req.staticParts);
});
This avoids string operations and is very explicit, therefore very robust.
Parsing the URL into staticParts without knowledge of the routes is problematic. For example, parsing the URL /street/house/25 based on keywords would lead to req.staticParts = "/street/house", but there is no matching route for it.

Snipcart - error: 'product-crawling-failed'

I'm trying to set up Snipcart for the first time. It seems pretty straightforward for the most part, but I'm running into some issues when I try to check out with the test payment card.
I'm working with just a vanilla front end, and Express on the back. I'm getting the same error every time:
A 'cart-confirmation' error occurred in Snipcart.
Reason: 'product-crawling-failed'
But the URL it's returning me in my console looks like it should be able to crawl for the product properly: https://myHerokuApp.herokuapp.com/shop/starry-night
<button class="snipcart-add-item"
data-item-id="starry-night"
data-item-price="79.99"
data-item-url="/shop/starry-night"
data-item-description="This is a sweet piece of art."
data-item-image="img/1.jpg"
data-item-name="The Starry Night">
Add to cart
</button>
I'm really confused at to what I'm doing wrong. Is there something I have to do with my express router? I've tried routing something like this just to see what would happen
router.get("/shop/:product", function (req, res, next) {
res.json({
"data-item-id": "starry-night",
"data-item-price": "79.99",
"data-item-url": "/shop/starry-night"
})
});
But that didn't make a difference.
I'm really hoping someone can spot what I'm doing wrong or point me in the right direction in the docs..
Thank you!
Attributes data-item-id and data-item-price are used with HTML crawler and are defined inside buy-button.
If you want to use JSON crawler, then you should return valid JSON with properties id and price. Also, price should be of type number. Change your backed like this:
router.get("/shop/:product", function (req, res, next) {
res.json({
"id": "starry-night",
"price": 79.99
})
});
Note: your server must be publicly available (not running in your localhost).

Specific URL path

I'm looking for a method to catch these urls:
https://my.server.com/subsite
https://my.server.com/subsite.html
... but not these:
https://my.server.com/otherpath/subsite
https://my.server.com/other/path/subsite
What I got so far is this code - but obviously I'm also catching the urls I do not want to get (from above):
var express = require('express');
let app = express();
app.get(/\/subsite(?:\.html)?$/, function(req, res) {
})
I tried to fix my code by inserting com before the regex but this does not seems to be a working solution: /.*com\/subsite(?:\.html)?$/.
How can I get around this issue?
This worked for me.
app.get(/.*com\/subsite(?:\.html)?$/, function(req, res) {
})
Here is where i tested it: https://regex101.com/r/42lhKg/1
You don't need to use a Reg Ex object, this will work fine:
app.get("/subsite(.html)?", function(req, res) {
/*...*/
})
Matches any path beginning with "subsite" and with possibility of a .html
Your Regex is missing a the constraint to make subsite appear only in the begging ^:
/^\/subsite(?:\.html)?$/
witch is the same as using just the string:
"/subsite(.html)?"
that I mentioned in the other answer.
Don't forget that in express you only care about the path and query part of the url.

how to pass a url as a "url parameter" in express?

In my express app I have a router listening to api/shorten/:
router.get('api/shorten/:longUrl', function(req, res, next) {
console.log(req.params.longUrl);
}
When I use something like:
http://localhost:3000/api/shorten/www.udemy.com
I get www.udemy.com which is what I expect.
But when I use:
http://localhost:3000/api/shorten/http://www.udemy.com
I get a 404 error.
I want to get http://www.udemy.com when I access req.params.parameter.
I'm not sure if you're still looking for a solution to this problem. Perhaps just in case someone else is trying to figure out the same thing, this is a simple solution to your problem:
app.get('/new/*', function(req, res) {
// Grab params that are attached on the end of the /new/ route
var url = req.params[0];
This way you don't have to sweat about any forward slashes being mistaken for routes or directories, it will grab everything after /new/.
You need to use encodeURIComponent in the client, and decodeURIComponent in the express server, this will encode all the not allowed characters from the url parameter like : and /
You need to escape as so:
escape("http://www.google.com")
Which returns:
"http%3A//www.google.com"
I just want to add that if you pass another params like ?param=some_param into your "url paramter" it will not show up in req.params[0].
Instead you can just use req.url property.

How to use parameters containing a slash character?

My MongoDB keys in person collection are like this:
TWITTER/12345678
GOOGLE/34567890
TWITTER/45678901
...
I define getPersonByKey route this way:
router.route('/getPersonByKey/:providerKey/:personKey').
get(function(req, res) { // get person by key
var key = req.params.providerKey + '/' + req.params.personKey;
// ...
}
);
Of course I'd prefer to be able to write something like this:
router.route('/getPersonByKey/:key').
get(function(req, res) { // get person by key
var key = req.params.key;
// ...
}
);
But this doesn't work, since GET http://localhost/getPersonByKey/TWITTER/12345678 of course results in a 404, since the parameter with the slash is interpreted as two distinct parameters...
Any idea?
Express internally uses path-to-regexp to do path matching.
As explained in the documentation, you can use a "Custom Match Parameter" by adding a regular expression wrapped in parenthesis after the parameter itself.
You can use the following path to get the result you need:
router.route('/getPersonByKey/:key([^/]+/[^/]+)').
get(function(req, res) { // get person by key
var key = req.params.key;
// ...
}
);
You can test and validate this or any other route here.
You can use this if your parameters has containing slashes in it
app.get('/getPersonByKey/:key(*)', function(req, res) { ... })
It works for me (at least in Express 4). In my case, I used parameters like ABC1/12345/6789(10).
Hopefully this useful.
app.get('/getPersonByKey/:key(*)', function(req, res) { ... })
This isn't working for me.
Swagger-ui will encode the path var before using it.
e.g. article/2159 will become article%2F2159.
When going directly with curl, it will not get encoded. the slash will remain a slash instead of %2F. And then the route is not matched.
Update: I'm on fastify. On express 4.X this works correctly.

Categories