Debugging .htaccess - apache

A few days ago I had a problem with writing my first htaccess in order to remove .html extension from URL. There were problems because I had a Windows server which I changed to Linux.
Now the issue is this:
I finally did manage to remove the .html extension from URL. What I can't do is to set an expiration date for all images (JPEG, PNG, SVG).
My working code is this (extension removal):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]
For Image caching parameter I added the following:
//Caching schema
<FilesMatch "\.(jpg|png|svg)$">
Header set Cache-Control "private, max-age=160704000"
</FilesMatch>
When I added the additional code above I got an internal server error.
I don't know what's going on to be honest. If I remove this additional code it will work but if I add this then it wont.
So do you guys have any ideas of how to add an Image caching parameter?? The additional code above doesn't work :(

UPDATE
After some research I tried this one:
<ifModule mod_headers.c>
ExpiresActive On
# Expires after 1 month
<filesMatch ".(gif|png|jpg|jpeg|ico|pdf|js|htm|html|txt)$">
Header set Cache-Control "max-age=2592000"
</filesMatch>
# Expires after 1 day
<filesMatch ".(css)$">
Header set Cache-Control "max-age=86400"
</filesMatch>
</ifModule>
Surprisingly this works. I tested it with gtmetrix.com .You think I should move forward now?

Set AllowOverride All in your server config for the host. Do this for the directory where your htaccess resides rather than the whole server, e.g.
<Directory /var/www/html/mysite/>
AllowOverride All
</Directory>
The issue is that your syntax is valid, but the server is refusing to process the request because AllowOverride is set to something other than 'All' which is what FilesMatch requires.
If you don't want to set AllowOverride to All for the .htaccess file, then you could move the <FilesMatch> statement into the host configuration for your site and it will work from there.

Related

Override FilesMatch rule of root htaccess by htaccess from subdirectory [duplicate]

I have an htaccess rule in a folder that disallows php scripts:
<FilesMatch "\.(?i:php)$">
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
That works just fine. The problem is that there is a specific php script I do want to be able to call (via ajax), so I want to add another rule after the deny that says "but if it is this specific file then allow it". I've done this successfully with other htaccess files in the folder that the file resides with something like this:
<Files ajax_file.php>
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
</IfModule>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
</Files>
The problem I am having is that I want to grant a single file access from the same htaccess as the original FilesMatch that blocks all .php files. I can't seem to make it work with adding a file path and am wondering if there is a better way to go about this. The file in question would be a few folders deeper than than the htaccess file that denies the php scripts.
I can see that this is a really old post but, since there is no marked answer I figured I'd try and solve this.
The code you need should look like this:
<FilesMatch "\.(?i:php)$">
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
That blocks access to all php files and set the priority as allow then deny, so that we can override the deny all later.
Then to allow access to the specific php file use this:
<Files ajax_file.php>
<IfModule !mod_authz_core.c>
Allow from all
</IfModule>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
</Files>
I can see from your OP that this isn't that different to your own, so I can only assume that by re-adding the Order declaration you are causing some weirdness to mess things up, since you already set the priorities in the initial [block all php] files declaration.
I think mod_rewrite is the best and easiest solution to your problem.
RewriteEngine on
# allow access to ajax_file.php
RewriteCond %{THE_REQUEST} ajax_file\.php [NC]
RewriteRule ^ - [NC,L]
#disallow access to other php files
RewriteCond %{THE_REQUEST} .+\.php [NC]
RewriteRule ^ - [F,L]
which linux distribution do you use? there are some htaccess configurators which make it easier to configure these files. you could write something like this
require valid-user
for every file that gets access.

Using HTTP Host in filesmatch in htaccess

I am trying to match my sitemap based on host and it doesn't seem to be working. Can you help me figure this out.
My sitemap is sitemap-localhost.xml since i am running on my local
I have tried
<FilesMatch (sitemap-%{HTTP:Host}.xml)>
Order Deny,Allow
Allow from all
</FilesMatch>
<FilesMatch "sitemap-%{HTTP:Host}.xml">
Order Deny,Allow
Allow from all
</FilesMatch>
<FilesMatch sitemap-%{HTTP:Host}.xml>
Order Deny,Allow
Allow from all
</FilesMatch>
But nothing seems to work. The problem is I have two domains pointing to the same folder in the server and the two domains have two sitemaps.
FilesMatch directive is designed to match against files only. You can not check HTTP_HOST header or URL path using this directive, only filename with its extension is allowed in the pattern.
If you want deny access to an xml file of a specific Host ,for example To deny access to thishost.com/sitemap.xml you can use mod-rewrite` .
RewriteEngine on
RewriteCond %{HTTP_HOST} ^thishost\.com$
RewriteRule ^/?sitemap\.xml$ - [R=403,L]
This will return a 403 error to clients if they visit thishost.com/sitemap.xml .
The leading slash ( /? ) in the pattern above is optional so that the Rule can work in both contexts htaccess and server.config .

Apache's RequestHeader is ineffective and effect is not seen in .htaccess

This is an apache question.
I set a header in my config files with RequestHeader. (local apache install)
I can see that works as per the output of a custom php script to dump headers: the header is there.
However a rule based on that header being present is not fulfilled in .htaccess.
The same .htaccess file works as expected on another server.
My added request header doesn't seem to be visible in .htaccess.
Any idea?
Apache conf:
RequestHeader set X-Forwarded-Proto "https"
.htaccess:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
That loops forever. But it works perfectly on a config behind an AWS load-balancer.
Thanks for helping agent420.
I finally found the solution... It takes either a clear understanding of Apache processing rules or some luck (latter in my case).
The working directive is:
RequestHeader set X-Forwarded-Proto "https" early
High, unsubtle, massive emphasis on the word 'early'.
That's all it took...
Hope that comes of some use to others.
Teebo
Do other rules in .htaccess work on this server? Because if they do not then it may be due to a configuration in Apache Config file (httpd.conf or apache2.conf depending on your distro)
Edit this file. Look for your website's directory...something like:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Change None toAll for the AllowOverride option. Restart the Apache service.
AllowOverride directive is used to allow the use of .htaccess within the web server to allow overriding of the Apache config on a per directory basis.
See this doc for details

Allow Access-Control for Subdomain in .htaccess

Having issues setting up a generic Allow Origin for any subdomain in my .htaccess file. The following works for a singular subdomain:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin http://subdomain.website.com
</IfModule>
But what I am looking for is something similar to this:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin {ANY SUBDOMAIN}.website.com
</IfModule>
I have tried using a simple *.website.com wildcard, but that does not seem to work. Do you have to specify exactly what is coming in?
If you're looking to do it for whatever subdomain was being requested, try the following:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin %{HTTP_HOST}
</IfModule>
If you need something more advanced, use mod_rewrite to set an environment variable and then refer to it using %{variable_name}e

Apache 2.2 conditional headers on response

I am trying to configure apache to send expires and cache-control headers on response but only if I receive some specific query string on the request.
For this I've tried configuring the server as follows:
RewriteCond %{QUERY_STRING} ^.*{whateverIWantInMyQueryString}.*$
RewriteRule ^(.*)$ - [env=CACHE_HEADERS:1]
<FilesMatch "\.(js|css|png|gif|GIF)$">
<IfDefine CACHE_HEADERS>
ExpiresActive On
ExpiresDefault "access plus 12 hours"
Header append Cache-Control "public"
</IfDefine>
</FilesMatch>
But this does not seem to work.
If I change the configuration as follows:
....
<IfDefine !CACHE_HEADERS>
....
It does work, so it seems IfDefine is not able to check that CACHE_HEADERS environment variable is being set.
I've also tried configuring things with Header directive and conditional based on the same environment variable using something like this:
RewriteCond %{QUERY_STRING} ^.*{whateverIWantInMyQueryString}.*$
RewriteRule ^(.*)$ - [env=CACHE_HEADERS:1]
<FilesMatch "\.(js|css|png|gif|GIF)$">
Header always set Cache-Control "max-age=3600, public" env=CACHE_HEADERS
Header always set Expires "Thu, 01 Jan 2015 00:00:00 GMT" env=CACHE_HEADERS
</FilesMatch>
.....
But this does not work either. So I am assuming this might be because of the environment variable that is being set by mod_rewrite, that for some reason is not being detected by neither IfDefine directive nor Header directive.
Does anyone know what may be causing this or why is this not working at all?
The reason why IfDefined is not working you can find here: Apache IfDefine conditionals in .htaccess
Basically it's that IfDefined only evaluates variables defined at command line not if you define them like you did or with SetEnv or SetEnvIf.
However as far as I know env= should work.