ReWrite Rule in IIS using RegEx - regex

For the last couple hours I tried to create a ReWrite Rule in IIS which does meet my requirements, but I just don't get it. So maybe someone can help me out :-)
What I have till now is the following:
Rewrite URL
index.php?page={R:1}&param={R:2}
RegEx Pattern
^(.*)/([0-9]+)
This is how I'd like to write my URLs at the end:
http://url.com/path1/path2/path3/param/ for example http://url.com/news/detail/1/
In this example I should have "news/detail" in "?page" and "1" in "?param".
With the rule I created so far that seems to work quite good, as long as I have a number at the end (param).
My only problem is that I want to make the number (param) optional.
Thanks a lot for your support.

I can't come up with something more permissive than this:
^([a-z-/]+)([0-9])?
Base on your comment Paths never have a number in it, I went a bit further and allowed only characters from a to z (use the ignore case option if needed).
This rule will match any of the following url:
news/detail/1/ => {R:1} = news/detail/ and {R:2} = 1
news/detail/1 => {R:1} = news/detail/ and {R:2} = 1
news/detail/ => {R:1} = news/detail/ and {R:2} is empty
news/detail => {R:1} = news/detail and {R:2} is empty
You probably will have to deal with the trailing / in your code.
The limitation comes from the fact that as far as I know, the regex in the rewrite rule doesn't support negative lookahead/lookbehind pattern.

To allow for the final match capture to be optional put a ? by it. Also specify that it will be at the by anchoring it with the end character $.
^(.*)/?(\d+)?$
I have also made the final / optional since if there is no digit you don't want match to fail if it does not have a / at the end (which should be optional).

Related

Fluentvalidation 6.4.1.0 support me with Incorrect regex

In my case, i want to validate for url image, some url is valid but result is wrong.
Eg: link image is "https://fuvitech.online/wpcontent/uploads/2021/02/bta16600brg.jpg" or "https://fuvitech.online/wp-content/uploads/2021/02/bta16-600brg.jpg" reponse "The image link is not in the correct format".
My code here:
RuleFor(product => product.Images)
.Length(1, 3000).WithMessage(Labels.importProduct_ExceedDescription, p => ImportHelpers.GetColumnName(typeof(ProductEntity).GetProperty(nameof(p.Images))))
.Matches(#"^(http:\/\/|https:\/\/){1}?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$").WithMessage(Labels.importProduct_UrlNotCorrect, p => ImportHelpers.GetColumnName(typeof(ProductEntity).GetProperty(nameof(p.Images))));
Please help me where the above regex is wrong. Thank you.
Try this:
NOTE the following regex pattern may trigger false positives and also may ignore valid image URLs, because it is very difficult to validate whether a given URL is valid.
^https?:\/\/(?:(?:[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+|[A-Za-z0-9]{2,})\.)+[A-Za-z]{2,}(?::\d+)?\/(?:(?:[A-Za-z0-9]+(?:(?:-[A-Za-z0-9]+)+)?\/)+|)[\w-]+\.(?:jpg|jpeg|png)$
Explanation
^ the start of a line/string.
https?:\/\/ match http with an optional letter s, followed by ://.
(?:(?:[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+|[A-Za-z0-9]{2,})\.)+ This will match things like foo-foo.bar-bar., foo.bar-bar. and foo.
[A-Za-z]{2,} this will match the TLD part, e.g., com, org, this part with the previous part will match things like foo-foo.bar-bar.com, foo.bar-bar.com or foo.com.
(?::\d+)? optional group of (a colon : followed by one or more digits) for port part.
\/(?:(?:[A-Za-z0-9]+(?:(?:-[A-Za-z0-9]+)+)?\/)+|) this check for two things, the first one is /uploads/public-images/, /uploads/images/, the second one is a single /.
[\w-]+ this part for the file name, e.g., bta16-600brg.
\.(?:jpg|jpeg|png) you can add here multiple extensions, you can allow uppercase letters by using for example, [Jj][Pp][Gg] for jpg.
$ the end of the line/string.
See regex demo
Thanks #SaSkY answer my question.
I found my mistake.
This source [.[a-z]{2,5}] only allows domain extensions from 2-5 characters. Example [.com] is valid. But in my case [.online] was not valid.
I changed to [.[a-z]{1,10}].

Regex, how to match all urls but one?

My Regex skills a minimum, I have been trying for a while now to get this to work:
I need to match all urls in one domain, but one (the login one).
Example:
Match: domain.com/ANYTHING-GOES-HERE
but
Not Match: domain.com/login
I don't actually need to match the domain.com part because that's always the same, what comes after it.
I have tried:
(?!\/login)\/.*
\/.*[^login]
Neither one seems to work as desired.
Update:
I should have explained that this is done in PHP. I don't have control over the actual code that runs the regex, but I do have control over how many regex I can have. So I could have one regex that matches everything, and then have one regex that matches or not matches "/login"
You're almost there:
// javascript
r = /domain\.com\/(?!login).+/
r.test("domain.com/ANYTHING-GOES-HERE") // true
r.test("domain.com/login") // false
This also rejects "domain.com/login/foobar", if you want it to be accepted, modify the regex to be
r = /domain\.com\/(?!login$).+/

Regex to match anything after /

I'm basically not in the clue about regex but I need a regex statement that will recognise anything after the / in a URL.
Basically, i'm developing a site for someone and a page's URL (Local URL of Course) is say (http://)localhost/sweettemptations/available-sweets. This page is filled with custom post types (It's a WordPress site) which have the URL of (http://)localhost/sweettemptations/sweets/sweet-name.
What I want to do is redirect the URL (http://)localhost/sweettemptations/sweets back to (http://)localhost/sweettemptations/available-sweets which is easy to do, but I also need to redirect any type of sweet back to (http://)localhost/sweettemptations/available-sweets. So say I need to redirect (http://)localhost/sweettemptations/sweets/* back to (http://)localhost/sweettemptations/available-sweets.
If anyone could help by telling me how to write a proper regex statement to match everything after sweets/ in the URL, it would be hugely appreciated.
To do what you ask you need to use groups. In regular expression groups allow you to isolate parts of the whole match.
for example:
input string of: aaaaaaaabbbbcccc
regex: a*(b*)
The parenthesis mark a group in this case it will be group 1 since it is the first in the pattern.
Note: group 0 is implicit and is the complete match.
So the matches in my above case will be:
group 0: aaaaaaaabbbb
group 1: bbbb
In order to achieve what you want with the sweets pattern above, you just need to put a group around the end.
possible solution: /sweets/(.*)
the more precise you are with the pattern before the group the less likely you will have a possible false positive.
If what you really want is to match anything after the last / you can take another approach:
possible other solution: /([^/]*)
The pattern above will find a / with a string of characters that are NOT another / and keep it in group 1. Issue here is that you could match things that do not have sweets in the URL.
Note if you do not mind the / at the beginning then just remove the ( and ) and you do not have to worry about groups.
I like to use http://regexpal.com/ to test my regex.. It will mark in different colors the different matches.
Hope this helps.
I may have misunderstood you requirement in my original post.
if you just want to change any string that matches
(http://)localhost/sweettemptations/sweets/*
into the other one you provided (without adding the part match by your * at the end) I would use a regular expression to match the pattern in the URL but them just blind replace the whole string with the desired one:
(http://)localhost/sweettemptations/available-sweets
So if you want the URL:
http://localhost/sweettemptations/sweets/somethingmore.html
to turn into:
http://localhost/sweettemptations/available-sweets
and not into:
localhost/sweettemptations/available-sweets/somethingmore.html
Then the solution is simpler, no groups required :).
when doing this I would make sure you do not match the "localhost" part. Also I am assuming the (http://) really means an optional http:// in front as (http://) is not a valid protocol prefix.
so if that is what you want then this should match the pattern:
(http://)?[^/]+/sweettemptations/sweets/.*
This regular expression will match the http:// part optionally with a host (be it localhost, an IP or the host name). You could omit the .* at the end if you want.
If that pattern matches just replace the whole URL with the one you want to redirect to.
use this regular expression (?<=://).+

Regex match url without file extension

I would like some help matching the following urls.
/settings => /settings.php
/657_46hallo => /657_46hallo.php
/users/create => /users.php/create
/contact/create/user => /contact.php/create/user
/view/info.php => /view.php/info.php
/view/readme - now.txt => /view.php/readme - now.txt
/ => [NO MATCH]
/filename.php => /unknown.php
/filename.php/users/create => /unknown.php
if the first part after the domain name is a filename ending with ".php"
(see last 2 examples) It should redirect to /unknown.php
I think I need 2 regular expressions
1st should be almost something like: ^/([a-zA-Z0-9_]+)(/)?(.*)?$
2nd to catch the direct filename "/filename.php" or "/filename.php/create/user"
so I can redirect to unknown.php
The 1st regular expression that I got almost works for the first part.
==============================================
request url: http://domain.com/user/create
regex: ^/([a-zA-Z0-9_]+)(/)?(.*)?$
replace http://domain.com/$1.php$2$3
makes: http://domain.com/user.php/create
Problem is it also matches http://domain.com/user.php/create
If someone could help me with both regular expressions that would be great.
If you want to match those .php cases you can try this:
^\/([a-zA-Z0-9_]+)(\/)?(.*)?$
See here on Regexr
If you want to avoid those cases try this:
^/([a-zA-Z0-9_]+)(?!\.php)(?:(/)(.*)|)$
See here on Regexr
The (?!\.php) is a negative look ahead that ensures that there is no .php at this place.
When all you have is a hammer...
While this probably could be solved with a regexp, it is probably the wrong tool for the job, unless you have constraints that MANDATE the use of regexps.
Split the string using '/' as the delimiter, see whether the first component ends with '.php'; if so, reject it, otherwise append '.php' to the first component and join the components back using '/'.

This regex matches and shouldn't. Why is it?

This regex:
^((https?|ftp)\:(\/\/)|(file\:\/{2,3}))?(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(((([a-zA-Z0-9]+)(\.)?)+?)(\.)([a-z]{2}
|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum))([a-zA-Z0-9\?\=\&\%\/]*)?$
Formatted for readability:
^( # Begin regex / begin address clause
(https?|ftp)\:(\/\/)|(file\:\/{2,3}))? # protocol
( # container for two address formats, more to come later
((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) # match IP addresses
)|( # delimiter for address formats
((([a-zA-Z0-9]+)(\.)?)+?) # match domains and any number of subdomains
(\.) #dot for .com
([a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum) #TLD clause
) # end address clause
([a-zA-Z0-9\?\=\&\%\/]*)? # querystring support, will pretty this up later
$
is matching:
www.google
and shouldn't be. This is one of my "fail" test cases. I have declared the TLD portion of the URL to be mandatory when matching on alpha instead of on IP, and "google" doesn't fit into the "[a-z]{2}" clause.
Keep in mind I will fix the following issues seperately - this question is about why it matches www.google and shouldn't.
Querystring needs to support proper formats only, currently accepts any combination of querystring characters
Several protocols not supported, though the scope of my requirements may not include them
uncommon TLDs with 3 characters not included
Probably matches http://www.google..com - will check for consecutive dots
Doesn't support decimal IP address formats
What's wrong with my regex?
edit: See also a previous problem with an earlier version of this regex on a different test case:
How can I make this regex match correctly?
edit2: Fixed - The corrected regex (as asked) is:
^((https?|ftp)\:(\/\/)|(file\:\/{2,3}))?(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(((([a-zA-Z0-9]+)(\.)?)+?)(\.)([a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum))([\/][\/a-zA-Z0-9\.]*)*?([\/]?[\?][a-zA-Z0-9\=\&\%\/]*)?$
"google" might not fit in [a-z]{2}, but it does fit in [a-z]{2}([a-zA-Z0-9\?\=\&\%\/]*)? - you forgot to require a / after the TLD if the URL extends beyond the domain. So it's interpreting it with "www.go" as the domain and then "ogle" following it, with no slash in between. You can fix it by adding a [?/] to the front of that last group to require one of those two symbols between the TLD and any further portion of the URL.
Your TLD clause matches "go" in google and the querystring support part matches "ogle" afterwards. Try changing the querystring part to this:
([?/][a-zA-Z0-9\?\=\&\%\/]*)?
google" doesn't fit into the "[a-z]{2}" clause.
But "go" does and then "ogle" matches "([a-zA-Z0-9\?\=\&\%/]*)?"