If a user goes to URL, say: http://www.domain.com/image/orange.jpg
but orange.jpg does not exist, however orange.png does, can .htaccess allow the user to find it?
That should be possible. mod_rewrite allows to check for the existance of files. And it allows multiple passes of rewriting in case you do not stop that process actively using the [L] flag. .
So have a try with something like this as a starting point (untested):
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/image/([^/.]).jpg$
RewriteCond %{REQUEST_URI} !-f
RewriteRule ^/image/([^/.]).jpg /image/$1.png
RewriteCond %{REQUEST_URI} ^/image/([^/.]).png$
RewriteCond %{REQUEST_URI} !-f
RewriteRule - /image/no-found [G,L]
The above applies if defined inside the central server configuration (per-host configuration). For .htaccess style files the syntax is slightly different: the leading slash (/) inside the RewriteRule must not be present in that case. If you have a choice do the rewriting in the server configuration. .htaccess style files are something like a workaround and very error prone. Try to avoid them if possible.
Note however that such setup is somewhat limited and annoying to maintain. Often it is a better alternative to setup a small wrapper script (probably php based) that processes the request and check a number of alternatives before deciding what response to send. You could rewrite requests to something like this:
RewriteEngine on
RewriteRule ^/image/([^/.])\..+$ /image.php?name=%1
Now you can serve that request with a script image.php where you can check for existing versions of images without haste and return headers and content to your liking.
Related
Found a problem with my site on NextJS. During development, I navigated the site using buttons and manually changing the browser address bar. It happened that I accidentally added a slash to the end, but my localhost server removed it and everything worked fine.
But everything changed when I uploaded my static application to the hosting. It automatically began to add these slashes when reloading the page. Because of this, my pictures on the site break.
As far as I understand, you need to correctly configure the .htaccess file.
Here is what it looks like now:
RewriteEngine On
RewriteRule ^([^/]+)/$ $1.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.html
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
RewriteRule ^([^/]+)/$ $1.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.html
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
Your existing rules are all expecting (or forcing) a trailing slash on all your URLs. So, if the canonical URL (and the URL you are linking to) does not include a trailing slash then all these rules essentially need to be reversed. However, there are other issues here (the first rule, for instance, is unconditionally rewriting the request to append the .html extension, which is repeated in the next rule with a condition.)
Try the following instead:
RewriteEngine On
# (OPTIONAL) Remove trailing slash if it happens to be on the request
# Exclude physical directories (which must end in a slash)
RewriteRule %{REQUEST_FILENAME} !-d
RewriteRule (.+)/$ /$1 [R=301,L]
# Rewrite request to corresponding ".html" file if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^([^.]+)$ $1.html [L]
Your original directives only handled URLs with one or two path depth (eg. /foo/ or /foo/bar/). The second rule above handles any path depth (if so required). eg. /foo, /foo/bar, /foo/bar/baz etc. (no trailing slash).
As an optimisation I've assumed your URLs that require rewriting do not contain dots (that are otherwise used to delimit the file extension).
Note that the RewriteRule pattern (first argument) matches against the URL-path only (not the query string). If there is any query string on the initial request then this is simply passed through by default. (With regards to the rewrite and client-side JS, the query string is available on the initial request and should be parsed as before.)
Because of this, my pictures on the site break.
This will happen if you are using relative URLs to your images. You should really be using root-relative (starting with a slash) or absolute URLs to resolve this issue. See also:
404 not found - broken links to CSS, images
I'm using create-react-app together with react-router. How can I make any of the following variations (I don't think I missed any):
www.example.com
example.com
http://example.com
http://www.example.com
redirect to:
https://example.com (notice the https secured, and no www.)
I created an .htaccess file with the following code:
<ifModule mod_rewrite.c>
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*) https://%{HTTP_HOST}/$1 [R,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !\/$
RewriteRule ^(.*) /
</ifModule>
<IfModule mod_headers.c>
<FilesMatch "sw\.js$">
Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
Header set Pragma "no-cache"
</FilesMatch>
</IfModule>
When I add that, the routes get directed to secured https, but the www is there when I type it in the url. How can I have the browser always redirect to not have www.?
The rediretion to another host should work better like that, note the hard wired target host name:
RewriteEngone on
RewriteCond %{HTTPS} off
RewriteRule ^/?(.*)$ https://example.com/$1 [R=301]
RewriteCond %{HTTP_HOST} !^example\.com$
RewriteRule ^/?(.*)$ https://example.com/$1 [R=301]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
Place those rules before any internal rewriting rules (your example shows a general rewriting to ?/).
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
Ive taken a copy of expressionengine from our production server to a dev server and its installed and running. I can access the admin console fine and Ive updated my paths.
The problem is that when I try and view my site the main page loads but no CSS is downloaded. The error Im getting is
The requested URL /presentation/layout was not found on this server.
I cant access the file from http://localhost/presentation/layout but I can access from
http://localhost/index.php/presentation/layout
Ive updated my .htaccess file from the following guide
https://docs.expressionengine.com/latest/urls/remove_index.php.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{REQUEST_URI} !/system/.* [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I can access the site now from http://localhost without the index.php but its still looking for it for the CSS file. Any idea how I can resolve this?
First thing: don't put your css file in a template unless you absolutely have to.
You only need dynamical css files if the styles are depending on the data in a channel like
{exp:channel:entries}
.{title} {
color: #{color_custom_field};
}
{/exp:channel:entries}
If you put it in a template it will be processed by the template parser on every page view. This will add extra queries/processing which isn't needed for a static file.
What version of EE are you on?
All of us EE guys are over at https://expressionengine.stackexchange.com/ by the way
I'm creating an AngularJS app and want to avoid the # in the URL. I learned that I needed to add the following .htaccess rules to make it work:
RewriteEngine On
Options FollowSymLinks
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]
That worked great. However, now my calls to my web services are not working. The web service files are inside an /api/ directory, e.g. http://example.com/api/. My guess is that when the api calls try to access those files, they also get redirected and break. So how can I modify the rules above to redirect everything to the homepage, except links that are going to any file inside the api folder? I tried to find an existing answer to this, but while there were many similar ones, none of them was exactly what I needed. Thanks!
I found the code I needed:
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /
That's all you need. Got it from: https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/
Synopsis:
localhost/root/admin is an existing folder
I want /root/admin to go to /root/index.php?url=admin without changing the url in the address bar.
The only except is if the requested file is an image
This is what I have written for the .htaccess file in localhost/root to try and do all this:
RewriteEngine On
RewriteBase /root/
RewriteCond %{REQUEST_URI} !index\.php$
RewriteCond %{REQUEST_URI} !(.*\.(png|jpg|gif))$ [NC]
RewriteRule (.*) index.php?url=$1 [QSA,L]
What this does instead is redirect localhost/root/admin to localhost/root/index.php and changes the url in the address bar to localhost/root/admin/?url=admin.
It will only not do this if I add a trailing slash (/) onto "admin".
I know that, on my mac laptop, this mod_rewrite code does exactly what it is meant to, but only when running it in the "Sites" folder and not in the localhost htdocs folder.
Any thoughts on what I can do to fix this?
I think you're just missing the "PT" flag to prevent an actual redirect. PT (Passthrough) means that Apache redirects the resource served internally, but the browser sees the same URL. (See the Apache wiki for more details: http://wiki.apache.org/httpd/RewriteFlags/PT)
RewriteEngine On
RewriteBase /root/
RewriteCond %{REQUEST_URI} !index\.php$
RewriteCond %{REQUEST_URI} !(.*\.(png|jpg|gif))$ [NC]
RewriteRule (.*) index.php?url=$1 [PT,QSA,L]
Note the only change was to add the flag. I tested this on my server and saw the behavior that I think you want.