How are '+' handled in ASP Net Core routes?
I have a route defined like this:
"/Test/{words}/{type:regex(^(AA|BB|CC)$)}/{search2}"
with parameters of the function being string[] words, string type, string search2
With different URLS:
/Test/word1+word2/AA/blablabla => 404
/Test/word1%20word2/AA/blablabla => Ok, words={"word1 word2"}
/Test/word1,word2/AA/blablabla => Ok, words={"word1","word2"}
I don't understand the 404. any idea why it happens? I would have translated the '+' with a space.
You must encode a space; it is correct to encode a space as +, but only in the query string; in the path you must use %20. For + you can use %2b. (Http 1.1)
Related
When I needed to add a dynamic segment to the URL, the first thing that came to mind was to try the following:
app.get('/one/*/two/*/three', (req, res, next) => {
// req.params as any)[0] - first dynamic segment
// req.params as any)[1] - second dynamic segment
});
Turns out, the code above works perfectly. What confuses me, however, I cannot find it anywhere in the official documentation, and any answer here about dynamic segments with ExpressJS suggests different things, none of them suggest use of asterisks.
Am I doing something wrong here? Or what am I missing?
From the official documentation about Routing:
Route paths
Route paths, in combination with a request method, define the
endpoints at which requests can be made. Route paths can be strings,
string patterns, or regular expressions.
The characters ?, +, *, and () are subsets of their regular expression
counterparts. The hyphen (-) and the dot (.) are interpreted literally
by string-based paths.
And:
This route path will match abcd, abxcd, abRANDOMcd, ab123cd, and so
on.
app.get('/ab*cd', (req, res) => { res.send('ab*cd') })
I was working with routes in .NET Core and I noticed that when I use the same route but passing it with a lowercase letter, I got access to the same page.
Example:
mydomain.com/Account/Login
mydomain.com/account/login
Why was there no distinction between uppercase and lowercase in this case? And I am not using services.AddRouting (options => options.LowercaseUrls = true); to allow this.
I just want to know how that letter distinction works and why it continues to work.
Quote from the Doc :
Text matching is case-insensitive and based on the decoded representation of the URL's path.
And services.AddRouting (options => options.LowercaseUrls = true); is just used to convert the route template to lowercase. But you can still access it with uppercase Url.
I'm overhauling a website that someone else built for my organization. It was originally set up with "not so great" anchor links which included spaces. I have replaced those anchors with new ones that will work better.
Example:
One of the old anchors looked like this /course/#To Have which browsers would luckily convert to /course/#To%20Have. I changed that anchor to this: /course/#to-have.
I'm now wanting to make sure that any anchors that may have been shared on social media or that could be linked to from other websites still work; I was planning on doing this via redirect in the .htaccess file, such as this one:
Redirect 301 /course/#To%20Have /course/#to-have
After some research I've found that this is not possible due to the # in the URLs. And I also have not seen examples where an anchor was redirected to another anchor.
Is this possible?
As mentioned in my comment, this is not possible with .htaccess.
Reason being: the hash part (known as the fragment) is not actually sent to the server, and so Apache would not be able to pick it up. Servers may only pick up everything before that, which is described in the Syntax section of this article.
As an alternative, I would recommend that you use JavaScript to convert the fragment before scrolling to its location. You can do that by pulling in the value of [window.]location.hash (the part in square parenthises is optional as location is also available in the global scope) if it exists, as shown below:
if (window.location.hash) {
// Function to 'slugify' the fragment
// #see https://gist.github.com/mathewbyrne/1280286#gistcomment-1606270
var slugify = function(input) {
return input.toString().toLowerCase().trim()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/&/g, '-and-') // Replace & with 'and'
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-'); // Replace multiple - with single -
}
// Now get the hash and 'slugify' it
var hash = slugify(window.location.hash.split('#')[1]);
// Go to the new hash by setting it
window.location.hash = '#' + hash;
}
The URL link below will open a new Google mail window. The problem I have is that Google replaces all the plus (+) signs in the email body with blank space. It looks like it only happens with the + sign. How can I remedy this? (I am working on a ASP.NET web page.)
https://mail.google.com/mail?view=cm&tf=0&to=someemail#somedomain.com&su=some subject&body=Hi there+Hello there
(In the body email, "Hi there+Hello there" will show up as "Hi there Hello there")
The + character has a special meaning in [the query segment of] a URL => it means whitespace: . If you want to use the literal + sign there, you need to URL encode it to %2b:
body=Hi+there%2bHello+there
Here's an example of how you could properly generate URLs in .NET:
var uriBuilder = new UriBuilder("https://mail.google.com/mail");
var values = HttpUtility.ParseQueryString(string.Empty);
values["view"] = "cm";
values["tf"] = "0";
values["to"] = "someemail#somedomain.com";
values["su"] = "some subject";
values["body"] = "Hi there+Hello there";
uriBuilder.Query = values.ToString();
Console.WriteLine(uriBuilder.ToString());
The result:
https://mail.google.com:443/mail?view=cm&tf=0&to=someemail%40somedomain.com&su=some+subject&body=Hi+there%2bHello+there
If you want a plus + symbol in the body you have to encode it as 2B.
For example:
Try this
In order to encode a + value using JavaScript, you can use the encodeURIComponent function.
Example:
var url = "+11";
var encoded_url = encodeURIComponent(url);
console.log(encoded_url)
It's safer to always percent-encode all characters except those defined as "unreserved" in RFC-3986.
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
So, percent-encode the plus character and other special characters.
The problem that you are having with pluses is because, according to RFC-1866 (HTML 2.0 specification), paragraph 8.2.1. subparagraph 1., "The form field names and values are escaped: space characters are replaced by `+', and then reserved characters are escaped"). This way of encoding form data is also given in later HTML specifications, look for relevant paragraphs about application/x-www-form-urlencoded.
Just to add this to the list:
Uri.EscapeUriString("Hi there+Hello there") // Hi%20there+Hello%20there
Uri.EscapeDataString("Hi there+Hello there") // Hi%20there%2BHello%20there
See https://stackoverflow.com/a/34189188/98491
Usually you want to use EscapeDataString which does it right.
Generally if you use .NET API's - new Uri("someproto:with+plus").LocalPath or AbsolutePath will keep plus character in URL. (Same "someproto:with+plus" string)
but Uri.EscapeDataString("with+plus") will escape plus character and will produce "with%2Bplus".
Just to be consistent I would recommend to always escape plus character to "%2B" and use it everywhere - then no need to guess who thinks and what about your plus character.
I'm not sure why from escaped character '+' decoding would produce space character ' ' - but apparently it's the issue with some of components.
I've noticed that when i send a url like this:
http://localhost:3000/register/register_user/?sig=zaQ/876CwJMEEmrJqAOYHyEKBXy2s03NDmk+3FsXPr4=
what comes through when I use it to compare to the expected result using params[:sig] in the controller is this:
zaQ/876CwJMEEmrJqAOYHyEKBXy2s03NDmk 3FsXPr4=
For some reason the '+' sign that was in the url at the 9th character from the end of the string has been converted to a space.
Not sure why that happens, whether it only happens with + signs or what.
The result returned by Digest::SHA256.base64digest(data) has this plus sign so my validation of the signature is failing.
What's the best way to fix this? Will it suffice in the general case just to convert '+' signs into spaces before the comparison or is the re some less ugly way to address?
You'll need to url encode it. Either do a search and replace for + with %2B or force the encoding using open-uri.
require 'cgi'
sig = "zaQ/876CwJMEEmrJqAOYHyEKBXy2s03NDmk+3FsXPr4="
puts CGI.escape(sig)
Tested it this time.
irb(main):008:0> require 'cgi'
=> true
irb(main):009:0> CGI.escape('zaQ/876CwJMEEmrJqAOYHyEKBXy2s03NDmk+3FsXPr4=')
=> "zaQ%2F876CwJMEEmrJqAOYHyEKBXy2s03NDmk%2B3FsXPr4%3D"
irb(main):010:0>