We have a website where we show clients creative work we have produced for them. We upload raw assets to a path like this:
x.com/clients/clientName/campaignName/size/
I have a PHP script which adds our branding, contact information and other information and pulls in the raw creative (usually a swf object). It is in this directory x.com/clients/index.php and it accepts a query string parameter ?path so it knows where to look for the creative.
I am trying to do an apache rewrite in .htaccess so that our designers can upload directly to the known folder structure but so that when you go to x.com/clients/clientName/campaignName/size/ it should rewrite to x.com/clients/index.php?path=clientName/campaignName/size/
I am currently using the following rewrite rule, which works for the first folder level e.g. x.com/clients/clientName/ does successfully rewrite, but any subsequent folders do not.
RewriteRule ^clients/([^/\.]+)/?$ /clients/index.php?path=$1 [L]
My RegEx's are terrible, so I'm stuck on what to do. Any help appreciated, thank you kindly.
Your regex is only matching urls like clients/xxxxxx/ because your pattern [^/\.]+ means one or many characters except "/" or "."
With your rule, it can't work for other subdirectories.
You can change your rule by this one
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
To avoid internal server error (code 500 which means an infinite loop in this case), you can do it this way
RewriteRule ^clients/index\.php$ - [L]
RewriteRule ^clients/(.+)$ /clients/index.php?path=$1 [L]
Is there a special reason you want to use regex? In my opinion you can just catch everything coming after /clients:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(.*/)?index\.php$ [NC]
RewriteRule ^clients/(.*)$ /clients/index.php?path=$1 [L]
The second line is to prevents redirect loops, because the index.php is also in the folder /clients and this would cause never ending redirects.
Related
I'm a bit stuck trying to figure out .htaccess and mod_rewrite properly.
I know that 90% of the problem is my terrible regex skill, 10% is due to apache (or my knowledge around its mod_rewrite best practices).
We have a web service that will soon be replaced by a new one, similar in functionality but different in terms of urls, params and other things.
What needs to happen for our users (most of them can't perform this update on their end, so we have to do it on our side; we also don't build the tool directly nor have access to the source code and we agreed with the vendor that these redirects will not be done on this new web service.
What I need apache to do, with mod_rewrite is to be able to replace parameters in the querystring one by one, based on a mapping I provide
Then it should replace certain separators; ultimately, it should replace the HTTP_REFERER as well and redirect with 301.
Here's the code I have so far:
RewriteEngine On
RewriteBase /
RewriteRule ^(.*/)?\.svn/ - [F,L] ErrorDocument 403 "Access Forbidden"
# One group of RewriteCond/RewriteRule per parameter
RewriteCond %{QUERY_STRING} ^([^&]*(?:&.*)?)?param=([^&]*(?:&.*)?)$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1param_changed=%2 [N,NE]
RewriteCond %{QUERY_STRING} ^([^&]*(?:&.*)?)?another_param=([^&]*(?:&.*)?)$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1another_param_modified=%2 [N,NE]
...
# This is meant to replace all | with , within the url
RewriteRule ^(.*)|(.*)$ $1,$2 [N]
# This is the one that should finalise the url replace
RewriteCond %{REQUEST_URI} ^http://this.old.url/api/1/access/activity.(xml|csv)([^&]*(?:&.*)?))$ [NC]
RewriteRule ^ https://the.new.one/api/activities/?format=1&%2$ [R=301,NE,L]
This is the result I'm expecting from an example call:
input:
http://this.old.url/api/1/access/activity.xml?reporting-org=GB-GOV-1|GB-1&recipient-country=BD&stream=True
output:
https://the.new.one/api/activities/?reporting_organisation=GB-GOV-1,GB-1&recipient_country_id=BD&format=xml
I'm trying it with the htaccess tester found here and these are the issues I am still facing:
rewrite of parameters works fine, but each parameter's modified version does not get propagated to the next RewriteCond/RewriteRule group
I can't have that | matched (it gets converted in %7C in the url, but regardless, I can't have it match).
The resulting url, at the end is:
https://the.new.one/api/activities/?format=1&%2$ which leads me to think that the regex I specify in the associated RewriteCond is wrong and doesn't match, so this works partially as a side effect (it's basically replacing the whole url I think) but I need it to get that .xml/csv format and the query string afterwards. I can't seem to be able to fix that regex to work as I need it to.
I know there's a lot in this post, so thanks In advance to whoever can help me sort out the 3 issues I'm still facing
I have been trying to work the regex out for this for a while now and I am struggling. Was hoping someone could help.
I have a website using apache mod_rewrite converting directories into get variables to 1 level. I am wanting to change this or add a seperate rule for the following
example.com/portfolio/plugins/jquery-tester
becoming
example.com/portfolio/handler.php?area=plugins&item=jquery-tester
I am trying to currently build up on php live regex but coming up trumps.
Try this:
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/portfolio/(.+)/(.+)$ /portfolio/handler.php?area=$1&item=$2 [L]
Having the handler in the same directory as what you're matching can cause potential problems though (that's why the RewriteCond is there to check so you don't end up with an infinite loop).
If you have other rewrite rules, you may need to check that there aren't any conflicts.
RewriteRule ^/portfolio/[a-zA-Z\-_]+/[a-zA-Z\-_]+$ /portfolio/handler.php?area=$1&item=$2 [L]
I''m sorry for asking the millionth Apache rewrite question here. I tried everything I know, but there is a small (hopefully) step that I'm looking for someone to shed a light for me.
I have a URL structure similar to this:
- assets
- assets/dist/19854/css/my.css
- css/my.css
I'm trying to rewrite assets/dist/19854/css/my.css file to css/my.css file in the root.
I have mod_rewrite enabled on my server, and I have basic understanding of rewrite rules, but it would be great if you could assist me with the Regex.
RewriteCond %{REQUEST_URI} ^assets/dist/([0-9/.]+)/(.*)$
RewriteRule ^assets/dist/([0-9]+)/(.*)$ $ [L,QSA]
Problem with the above rule is the it rewrite to ./19854, but I'm actually interested in the second expression's match. If possible, I'd also like to make sure the css/my.css file exists first.
Thanks in advance!
Edit:
Thanks for the comments and the answer. To further explain my case, this is a small site that uses a CDN, and everytime a new build is up, the number in assets/dist/[0-9] gets changed, so all assets' source URL gets changed. But I'm using a CSS compiler to compile CSS files, so CSS files reside in the same folder (css/my.css).
I have some other rewrites so I'm making my RewriteConds more strict.
So far, the above rewrite matches the numeric part, but I'm trying to rewrite to the URL right after the numeric part.
I believe you're attempting in other way round. You can use this code in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteBase /
# route to /css/my.css if it exists
RewriteCond %{DOCUMENT_ROOT}/$1 -f [NC]
RewriteRule ^assets/dist/.+?/(css/my\.css)$ $1 [L,NC]
I am working on a client's site that used to have all .swf files in directories via product code eg. g18/g18_flashfile.swf but now i've moved them into assets/flash/g18_flashfile.swf
I have tried to mod_rewrite the request to the new location due to external sites hotlinking to the file. This just error 500s
RewriteRule ^([^/]+)/([^.]+)\.swf$ assets/flash/$1/$2\.swf [L]
I also cannot just do a redirect anything as I am already using the following
RewriteRule ^(.*)/$ product.php?ref=$1 [L]
Any help would be great as I am scratching my head on this one.
EDIT
Whats even stranger is when I do
RewriteRule ^([^/]+)/([^.]+)\.swf$ assets/flash/$1/$2\.html [L]
It works (obviously it 404s because there isn't a .html file) but the rewrite works. Does anyone know if swf are some kind of term used in mod_rewrite?
The regular expression
^([^/]+)/([^.]+)\.swf$
matches both g18/g18_flashfile.swf and assets/flash/g18_flashfile.swf. Since the L flag might not work as you expected, this is a problem.
Just change the regular expression so that it doesn't match your rewritten path:
RewriteRule ^([^/]+)/([^/.]+)\.swf$ assets/flash/$1/$2\.swf [L]
Hi I have a problem.
I want to get all requests to redirect to index file in main directory and I've achieved this but there are problems with relative paths.
When I put address like: mydomain.com/something it works ok as the paths are relative to the main directory.
The problem is when I put something like: mydomain.com/something/somethingelse.
the .htaccess file:
Options FollowSymLinks
RewriteEngine On
# ignore anything that's an actual file
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
# redirect all other traffic to the index page
RewriteRule . index.php [L]
Any ideas on how to get css/js working?
Edit:
The problem is that css/js files aren't loaded when the path entered have multiple slashes like:mydomain.com/something/somethingelse
It is no doubt better to use absolute path for static files (css, js, images etc). But if you lots of those instances in several pages then consider using HTML base tag to specify a default URL for relative paths. eg:
<base href="http://www.example.com/static/" />
Using the <base>-tag is a nice solution and most browsers seem to handle it well. Except there are some issues with IE, as was to be expected... Apparently you can also run into some other funny problems, see discussion here.
So for people where this is not an option, i have looked into the alternative (the "hard way").
Usually you store css/js/static images/other stuff like this:
index.php
js/
css/
imgs/
and you want the javascript and stylesheets etc. to be available, no matter how many slashes there are in the url. If your url is /site/action/user/new then your browser will request
/site/action/user/css/style.css
/site/action/user/css/framework/fonts/icons.ttf
/site/action/user/js/page.js
/site/action/user/js/jquery/jquery.min.js
/site/action/user/js/some/library/with/deep/dir/structure/file.map
So here are some rewrite rules for apache to solve this... First, if the target actually exists on disk, do not rewrite:
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [L,QSA]
In words, IF reqest filename is a directory OR IF request filename is a file then do not rewrite (-), last rule (L) and pass any GET parameters (QSA, query string append). You can also use
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^.*$ - [L,QSA]
if you also need symlinks. Next we want the javascript and stylesheets to be found even if the requests assume a wrong base directory as shown above.
RewriteRule ^.*/js/(.*)$ js/$1 [L]
RewriteRule ^.*/css/(.*)$ css/$1 [L]
The pattern is pretty obvious, just replace 'css' with the directory name. There is still a problem with this, especially for large websites with lots of javascript and stylesheets, libraries etc. - The regex is greedy. For example, if you have a javascript directory like this:
js/some/library/js/script.js
and your request goes to /site/action/user/new, the browser will request /site/action/user/new/js/some/library/js/script.js, which the rewrite-engine will then rewrite to
js/script.js
because the first .* is greedy and matches /site/action/user/new/js/some/library. Switching to non-greedy regex does not really make sense, since "the rewrite engine repeats all the rules until the URI is the same before and after an iteration through the rules."
There is another problem, and that is that for every directory that needs to be exempted from rewriting, a relatively "expensive" regex is needed. Both problems can be fixed by just putting every static component into a subdirectory with an "unusual" name (and really this is the best solution imo - anyone with a better idea please post it).
The directory structure would then look like this:
index.php
mystrangedir/js/
mystrangedir/css/
mystrangedir/imgs/
Of course, this needs to be inserted everywhere in the code - for projects with a large existing codebase this can be tricky. However, you only need a single regex for directory exemption then:
RewriteRule ^.*/mystrangedir/(.*)$ mystrangedir/$1 [L]
Automated build systems (like gulp, grunt....) can be used to check if "mystrangedir" does not exist as directory anywhere below itself (which would again throw off the rewrite engine).
Feel free to rename mystrangedir to something more sensible like static_content but the more sensible it gets, the more probable it is that the directory name is already used in some library. If you want an absolutely safe directory name that has certainly never been used before, use a cryptographic hash, e.g. 010f8cea4cd34f820a9a01cb3446cb93637a54d840a4f3c106d1d41b030c7bcb. This is pretty long to match; you can make a tradeoff between uniqueness and regex performance by shorting it.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
Should obviously work despite the comments.
Try to add the RewriteLog and RewriteLogLevel directive to give us better details.
This is a path resolution issue: When using the relative path ./css on the base path /something it is resolved to /css while on /something/somethingelse it is resolved to /something/css.
This can’t (or rather shouldn’t) be fixed with mod_rewrite. Use absolute paths instead of relative paths, so /css instead of ./css.