mod_rewrite help to change Content-disposition based on URI - apache

I have a directory of mp3 files want to have be able to serve them inline or giving the user an option to download based on the request URI.
/media/file1.mp3 -- in this case, I just want to serve the file and let the browser play it.
/media/download/file1.mp3 -- in this case, I want to make it easy for a user to download the file instead.
I have been able to accomplish this with mod_rewrite and php (using the header() and readfile() function) but I would rather do it all with mod_rewrite, mod_header etc if possible.

IfDefine will check variables set on start-up of Apache so that won't work. A valid config would be:
SetEnvIf Request_URI ^/media/download/ force-download
Header set Content-Disposition attachment env=force-download
Also changing the Content-Type is not necessary to force a download.

With mod_rewrite you can only change some specific header fields but to which the Content-Disposition header field doesn’t belong. You could only change the Content-Type header field:
RewriteRule ^media/[^/]+\.mp3$ - [L,T=audio/mpeg]
RewriteRule ^media/download/[^/]+$ - [L,T=application/octet-stream]
And if you want to use a mod_headers+mod_setenvif solution:
SetEnvIf Request_URI ^/media/download/ force-download
<IfDefine force-download>
Header set Content-Disposition attachment
Header set Content-Type application/octet-stream
</IfDefine>

If you want to base rule on parameters in URI, here is the logic / syntaxe (adapt RewriteCond) :
RewriteCond %{QUERY_STRING} ^dl=1$
RewriteRule ^ - [L,E=FORCEDOWNLOAD:1]
Header set Content-Disposition attachment env=FORCEDOWNLOAD
Here, we force download if the only parameter is "dl=1"

Related

In htaccess, how to set a response header for all URLs of except one?

I want to use this rule:
<IfModule mod_headers.c>
Header always set X-FRAME-OPTIONS "DENY"
</IfModule>
But only for the front pages of my website.
I.e. I have a backoffice : example.com/gestion for which I don't want the rule to apply and I want to have the rule applied only for example.com (so all URLs without gestion)
Any idea ?
Try something like this using an Apache <If> expression to match all URLs, except for any URL that starts /gestion or contains multiple path segments or contains dots (ie. actual files).
For example:
<If "%{REQUEST_URI} =~ m#^/(?!gestion)[\w-]*$#">
Header always set X-FRAME-OPTIONS "DENY"
</If>
This uses a negative lookahead to avoid matching any URL that starts /gestion.
I'm assuming that your "front page" URLs only consist of single path segments containing characters in the range [0-9a-zA-Z_-].
The <IfModule> wrapper is not required (unless this is optional and you are using the same config on multiple server's where mod_headers may not be enabled - unlikely).

How can i add current URL to .htaccess CSP header dynamically?

I'm currently working on Shopify app, one of their main requirement is to add an iframe-protection. here is more info
Currently, to resolve this I need the CSP to set should be in this format :
Content-Security-Policy: frame-ancestors https://shopify-dev.myshopify.com https://admin.shopify.com;
The https://shopify-dev.myshopify.com in above code should be the merchant/ requester domain.
What I tried?
I created .htaccess file with following, it's not adding the dynamic url.
<IfModule mod_rewrite.c>
RewriteEngine On
Header set Content-Security-Policy "frame-ancestors '%{HTTP_HOST}' 'https://admin.shopify.com';"
</IfModule>
This is what I'm getting in console:
Apache
On Apache, you would need to do it like this instead:
### Apache ###
Header set Content-Security-Policy "frame-ancestors https://%{HTTP_HOST}e https://admin.shopify.com;"
Note the e after %{HTTP_HOST}e (specific syntax for mod_headers). I've also removed the single quotes (not present in the Spotify example) and included the https:// protocol.
The <IfModule> and RewriteEngine On directives are irrelevant here.
Reference:
https://httpd.apache.org/docs/current/mod/mod_headers.html#header
UPDATE:
LiteSpeed
However, if you are using LiteSpeed (as opposed to Apache) you will instead need to first explicitly assign the Host header to an environment variable and use this in the Header directive instead. (Apache is able to access server variables directly using this syntax, but not LiteSpeed.)
For example:
### LiteSpeed ###
# Assign the "Host" header to an env var "HOSTNAME"
SetEnvIf Host "(.*)" HOSTNAME=$1
# Use "HOSTNAME" (env var) instead in the Header directive
Header set X-Content-Security-Policy "frame-ancestors https://%{HOSTNAME}e https://admin.shopify.com;"
Attempting to use the syntax %{HTTP_HOST} (as you originally had) on Apache would have resulted in a 500 Internal Server Error (with the error "Unrecognized header format %" being reported in the error logs). However, on LiteSpeed this just outputs the literal string {HTTP_HOST} and no error.

Read header into environment variable in Apache 2.2?

I want to process a request header using a custom rewrite map.
Therefore I want to have the content of the header in an environment variable.
I have not found a way to do that with mod_headers and/or mod_rewrite.
Any help is appriciated.
Mod_rewrite example for the request header "X-Forwarded-For":
RewriteRule .* - [E=X-Forwarded-For:%{HTTP:X-Forwarded-For}]

Set Content-Disposition header to attachment only on files in a certain directory?

I've got this this rule in my htaccess file to force linked files to download rather than open in the browser:
<FilesMatch "\.(gif|jpe?g|png)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
Is there a way to alter the RegExp so it only applies to files in a certain directory?
Thanks
Like #gumbo said, put the .htaccess file in the highest level folder you want to affect. and those settings will trickle down to sub folders. You may also want to make sure the headers module is enabled before using this in your htaccess file. The following line will generate an error if the headers module is not enabled:
Header set Content-Disposition attachment
here's an example that forces download of mp3 files only if the headers module is enabled:
<IfModule mod_headers.c>
<FilesMatch "\.(mp3|MP3)$">
ForceType audio/mpeg
Header set Content-Disposition "attachment"
Allow from all
</FilesMatch>
</IfModule>
Note: it does not enable the module, it just ignores anything inside the IfModule tags if the module is not enabled.
To enable apache modules you'll either need to edit your httpd.conf file or in wamp server you can click the wamp tray icon and select "Apache -> Apache Modules -> headers_module" or make sure it is checked.
You will probably need to put the directives in the .htaccess file in the particular directory.
Put it in a <Location> directive, and/or modify the regex to exclude slashes or as appropriate.

how to have apache always return code 200 with data instead of 304?

I would like to have Apache HTTPD return response code 200 with data of resource request via a GET instead of returning response code 304 with no data. Any one have an idea how to do that?
Thanks in advance
remove the header, add the following into the httpd.conf file
<FilesMatch "\.(filetype1|filetype2)$">
RequestHeader unset If-Modified-Since
RequestHeader unset If-None-Match
</FilesMatch>
Add the following directive to your apache config file
RequestHeader unset If-Modified-Since
This will ignore IF-Modified-Since header sent from client so you will get not 304 Not Modified response.
Don't send it any cache-related headers (If-Modified-Since, If-None-Match and friends) when making the request. This informs the server that the client doesn't cache, and makes it always return data.
I'm not sure I fully understand your question. I assume you want the provide a normal HTTP answer if the client uses a correct URL, and a default page (with status 200) when the client uses a non-existing URL.
If this is the case, it can be achieved like that:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*+ /dummy.html
The first line is a condition that the URL doesn't macht an existing file on the web server. If that condidition holds, the second line is executed which serves a dummy page to the client.