When using Express' URL parameter functionality, it seems that parameters are automatically decoded. That is, percent-encoded entities are resolved to their normal form. %20 is replaced with a space.
However, a plus + is not replaced with a space. This is presumably because Express is using decodeURIComponent() internally, which also does not replace plus + with a space. Simple example code:
app.get('/:sourceFile', function (req, res, next) {
console.log(req.params.sourceFile);
});
If you request /test%20test, then you get test test on the console. If you request /test+test, then you get test+test on the console.
Is there a way to change this mode of operation in Express 4? Is this a bug?
You are trying to use + to represent a space in the "URI part" of your request. You can't do that. A plus sign is translated to a space only in query strings.
It is not a bug. In URI specs (page 12/13 https://www.rfc-editor.org/rfc/rfc3986), plus sign is a reserved character, not meant to be translated as a space.
Related
I'm trying to send a request to my Nestjs application, with just plain string in the request body, for example:
test23+Se5+345
Then in my application, I have a middleware, where I need to do something with this string.
The problem is when I access request body in middleware const requestBody = Object.keys(req.body)[0];, this string looks like this:
test23 Se5 345
All of the + symbols are substituted by
I don't have additional convertings before this, and I know that middleware runs first in the request lifecycle. I think maybe there is some issue with body-parser, but I don't know yet how to fix this.
This is because symbol + is treated as space, so before send it, you need to encode your + characters to %2b. More here: How to encode the plus (+) symbol in a URL
I'm having an issue with a NodeJS REST api created using express.
I have two calls, a get and a post set up like this:
router.get('/:id', (request, response) => {
console.log(request.params.id);
});
router.post('/:id', (request, response) => {
console.log(request.params.id);
});
now, I want the ID to be able to contain special characters (UTF8).
The problem is, when I use postman to test the requests, it looks like they are encoded very differently:
GET http://localhost:3000/api/â outputs â
POST http://localhost:3000/api/â outputs â
Does anyone have any idea what I am missing here?
I must mention that the post call also contains a file upload so the content type will be multipart/form-data
You should encode your URL on the client and decode it on the server. See the following articles:
What is the proper way to URL encode Unicode characters?
Can urls have UTF-8 characters?
Which characters make a URL invalid?
For JavaScript, encodeURI may come in handy.
It looks like postman does UTF-8 encoding but NOT proper url encoding. Consequently, what you type in the request url box translates to something different than what would happen if you typed that url in a browser.
I'm requesting: GET localhost/ä but it encodes it on the wire as localhost/ä
(This is now an invalid URL because it contains non ascii characters)
But when I type localhost/ä in to google chrome, it correctly encodes the request as localhost/%C3%A4
So you could try manually url encoding your request to http://localhost:3000/api/%C3%A2
In my opinion this is a bug (perhaps a regression). I am using the latest version of PostMan v7.11.0 on MacOS.
Does anyone have any idea what I am missing here?
yeah, it doesn't output â, it outputs â, but whatever you're checking the result with, think you're reading something else (iso-8859-1 maybe?), not UTF-8, and renders it as â
Most likely, you're viewing the result in a web browser, and the web server is sending the wrong Content-Type header. try doing header("Content-type: text/plain;charset=utf-8"); or header("Content-type: text/html;charset=utf-8"); , then your browser should render your â correctly.
I've created an Azure C# HTTP triggered function with a route url: subscriptions/{token}/t. It works fine for urls such as subscriptions/blah/t but it fails with a 404 for parameters that contain encoded slashes: subscriptions/blah%2fblah/t. Any way around this ?
Before we get into debates, {token} is a URL encoded Base64 string which will naturally contain slashes.
This issue seems to persist.
I found out that it can be resolved by double-escaping the string, that is, applying escaping recursively two times.
token = escape(escape(token));
In .NET you can use URI.EsacpeDataString()
In JS you can use encodeURIComponent()
Note, that single escaping does not work reliably with Azure functions
but it fails with a 404 for parameters that contain encoded slashes: subscriptions/blah%2fblah/t.
It is make sense because 'subscriptions/blah%2fblah/t' is equal to 'subscriptions/blah/blah/t'. I suggest you define your own encode rule for slashes. For example, you could convert all the slashes to '[[-]]'. Your token will be like this 'subscriptions/blah[[-]]blah/t'. After received the token, you could convert the special characters back.
token = token.Replace("[[-]]", "/");
I'd like to get a specific param using ExpressJS with "#" instead of "?" in the url...
My URL :
http://localhost:3000/#access_token=LMkdfkdmsklmfdkslklmdskfmsda
I'd like to get "access_token" and "req.params.access_token" doesn't work...
Anthony
Short answer: you can't.
Longer answer: fragment identifiers (that's the part after the #) are supposed to be evaluated on the client and are not supposed to be sent to server. Your express app has no way of knowing them.
You could try to convert them to query parameters or path variables (i.e. by handling fragment identifier change in javascript) to make them visible server-side.
I'm attempting to implement permalinks, in the form /2013/02/16/title-with-hyphens. I'd like to use route parameters. If I try the following route:
app.get('/:href', function(req, res) { });
...then I get a 404, presumably because Express is only looking for one parameter, and thinks that there are 4.
I can work around it with /:y/:m/:d/:t, but this forces my permalinks to be of that form permanently.
How do I get route parameters to include slashes?
It seems that app.get("/:href(*)", ...) works fine (at least in Express 4). You will get your parameter value in req.params.href.
It will also be fired by / route, which is probably not what you want. You can avoid it by setting app.get('/', ...) elsewhere in your app or explicitly checking for an empty string.
Use a regular expression instead of a string.
app.get(/^\/(.+)/, function(req, res) {
var href = req.params[0]; // regexp's numbered capture group
});
Note that you cannot use the string syntax (app.get('/:href(.+)')) because Express only allows a small subset of regular expressions in route strings, and it uses those regular expressions as a conditional check for that particular component of the route. It does not capture the matched content in the conditional, nor does it allow you to match across components (parts of the URL separated by slashes).
For example:
app.get('/:compa([0-9])/:compb([a-z]/')
This route only matches if the first component (compa) is a single digit, and the second component (compb) is a single letter a-z.
'/:href(.+)' says "match the first component only if the content is anything", which doesn't make much sense; that's the default behavior anyway. Additionally, if you examine the source, you'll see that Express is actually forcing the dot in that conditional to be literal.
For example, app.get('/:href(.+)') actually compiles into:
/^\/(?:(\.+))\/?$/i
Notice that your . was escaped, so this route will only match one or more periods.
You can do this with regex routing
app.get('/:href(\d+\/\d+\/\d+\/*)', function(req, res) { });
I don't know if the regex is right, but you get the idea
EDIT:
I don't think the above works, but this does
app.get(/^\/(\d+)\/(\d+)\/(\d+)\/(.*)/, function(req, res) { });
Going to http://localhost:3000/2012/08/05/hello-i-must-be yeilds req.params = [ '2012', '08', '05', 'hello-i-must-be' ]
You can use this if your parameters has include slashes in it
app.get('/:href(*)', function(req, res) { ... })
It works for me. In my case, I used parameters like ABC1/12345/6789(10).
Hopefully this useful.