how to compare the current time to a variable in a .htaccess - apache

I would like to make a redirection after a deadline on my site.
currently everything works correctly if I write this :
RewriteEngine On
SetEnv DEADLINE 16/06/2022_19h30
RewriteCond %{TIME_DAY}/%{TIME_MON}/%{TIME_YEAR}_%{TIME_HOUR}h%{TIME_MIN} >=16/06/2022_19h30
RewriteRule ^index.php$ read_only/index.html [L]
the advantage of using an environment variable is that I can use it elsewhere in a PHP file
So is there a way to test between the current time and the DEADLINE variable?

You can do this but you need to set your variable using SetEnvIf directive, so that it is available for evaluation in .htaccess RewriteCond:
Define this variable first:
SetEnvIf Host ^ DEADLINE=20220616193000
Then use it in .htaccess using RewriteCond expressions:
RewriteEngine On
RewriteCond expr "%{TIME} -ge env('DEADLINE')"
RewriteRule ^index\.php$ read_only/index.html [L,NC]
Due to use of expr in RewriteCond, it will require Apache 2.4+

Related

REQUEST_URI rewrite incl. query string

I have a WordPress plug-in and theme that are malforming a URL call to an external css file. I will fix that later, but until then, I need to do a redirect so the css is getting served correctly.
REQUEST_URI contains the full path, so why doesn't this work?
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/?wp-content/plugins/jetpack/css/%22https:/fonts.googleapis.com/css?family=Open+Sans%22$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/?wp-content/plugins/jetpack/css/"https:/fonts.googleapis.com/css?family=Open+Sans"$
RewriteRule ^(.*)$ https://fonts.googleapis.com/css?family=Open+Sans [R,L]
</IfModule>
Note 1: I have tried several combinations of escaping characters in the RewriteCond. Nothing works.
Note 2: I am using flag [R,L] for testing, to prevent browser caching. Will change to [R=301,L] later.
Note 3: I have tested to verify that the problem is with the RewriteCond, not the RewriteRule.
UPDATE:
OK, so this was a bad question and a dumb mistake. Even though raw REQUEST_URI contains the query string, mod_rewrite specifically does not allow query string to be in REQUEST_URI for matching purposes. Hence, QUERY_STRING instead. I thought that it could be done either way.
I don't have a true query string in my REQUEST_URI -- I have the query string that is in a string that I wanted to match -- so that is why I didn't go to QUERY_STRING at the outset. But mod_rewrite still sees the ? as a typical query string start.
Sorry, guys. I can handle it like this until I fix the underlying problem in WordPress:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/?wp-content/plugins/jetpack/css/%22https:/fonts.googleapis.com/css(.*)$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/?wp-content/plugins/jetpack/css/"https:/fonts.googleapis.com/css(.*)$
RewriteRule ^(.*)$ https://fonts.googleapis.com/css?family=Open+Sans [R,L]
</IfModule>
With WordPress, always remember to put your rewrites above the WordPress rewrites.

How to pass Apache environment variable to url in .htaccess

I am setting a apache environment variable through php function, apache_setenv.
apache_setenv("EXAMPLE_VAR", "Example Value");
But I am having problem accessing this variable inside .htaccess I am not able to use this env variable inside .htaccess in anyway. but I can access it through php getenv().
And problem is not only by setting variable through php I am unable to access env variable set by .htaccess itself.
I've tried
Suppose env variable to be www.domain.com.
RewriteEngine On
RewriteCond ^(.*)$ test.php?id=%{ENV:VARIABLE} [L]
&
RewriteEngine On
RewriteCond %{ENV:VARIABLE} ^www.(.+)
RewriteRule ^ test.php?id=%1 [L]
And similar other test to just verify that env variable are set and functioning.
Mod_env and mod_rewrite is on.
Variable set using SetEnv directives are not seen by mod_rewrite due to sequence of module loading by Apache. Use SetEnvIf instead like that:
SetEnvIf Host ^ VAR=/foo/bin
Then use it in mod_rewrite rules:
RewriteEngine On
RewriteCond %{ENV:VAR} =/foo/bin
RewriteRule ^home/?$ /something [L,NC]

Can I pick of environment variables inside .htaccess somehow?

I have a set of apache (2.4.25) sites that use mod_vhost_alias so the one vhost services multiple subdomains.
I want to be able to set a environment variable, say
<VirtualHost _default_:443>`
ServerNameAlias *.whatever-it-is.com
SetEnv HOME_URL https://www.whatever-it-is.com/
# etc
then in my various sites .htaccess files pick up that variable. So a site might allow access to a subfolder or a specific file and redirect everything back to the home site.
php_flag engine off
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/?
RewriteCond %{REQUEST_URI} !^/myapp[/]?
RewriteCond %{REQUEST_URI} !^favicon.ico
RewriteRule (.*) %{HOME_URL} [R=301,L]
# ^--- not working, how would you do it?
then in the case where I need to change the home_url across all sites, I can just apply it in the vhost and each of the dozens of subdomain sites will pick it up.
* also tried
RewriteRule (.*) %{ENV:HOME_URL} [R=301,L]
http://httpd.apache.org/docs/2.0/env.html
The %{ENV:variable} form of TestString in the RewriteCond allows mod_rewrite's rewrite engine to make decisions conditional on environment variables...
Use SetEnvIf to set your environment variable so that it is available for mod_rewrite later in .htaccess.
Inside VirtualHost config have it like this:
SetEnvIf Host ^ HOME_URL=https://www.whatever-it-is.com/
Then inside .htaccess have a simple rule:
RewriteEngine On
RewriteRule .* %{ENV:HOME_URL} [R=301,L]
Make sure to clear your browser cache before testing this change.

Mod Rewirte for CalDav and CardDav urls in Owncloud

I want to shorten my owncloud caldav and carddav urls.
currently the urls are :
https://site.mysite.com/owncloud/remote.php/caldav/principals/edison/
https://site.mysite.com/owncloud/remote.php/carddav/addressbooks/edison/contacts
Note : The name edison and what ever follows after that is dynamic it will change depending on the users.
I want it to be
https://site.mysite.com/caldav/principals/edison/
https://site.mysite.com/carddav/addressbooks/edison/contacts
.htaccess file contains
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !\.sso/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Eg:
If the user request for https://site.mysite.com/caldav/principals/edison/ . Then it should redirect to https://site.mysite.com/owncloud/remote.php/caldav/principals/edison/
How can it be done using mod_rewrite ?
mod_rewrite Prepend Path to Requested URL with Dynamic Portion
Starting at server root, enter the requested URL path in the RewriteRule "pattern" parameter, and the desired path in the "substitution" parameter. In the form:
RewriteRule pattern substitution [flags]
In this case:
RewriteRule ^caldav/principals/edison/$ owncloud/remote.php/caldav/principals/edison/ [L]
If a portion of the URL (between slashes) varies and you don't want to (or can't) write a rule for every situation then use the regular expression ([^/]+) to capture the dynamic portion and inject it into your substituted path using the RE capture variable $1:
RewriteRule ^caldav/principals/([^/]+)/$ owncloud/remote.php/caldav/principals/$1/ [L]
The first set of parenthesis is $1, the second set is $2, etc. And capturing parenthesis can be nested.
Put the more specific rules higher in the rules list, and more general rules lower in the list. So I suggest putting this rule first, right after RewriteBase /.

How to use SetEnv with a URL parameter

I'm trying to implement language switching in .htaccess, and the only thing left now is to handle clients which don't support cookies. To do that, I must set prefer-language when the user clicks a link with a language parameter.
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (?:^|&)language=(en|fr|no)
RewriteRule ^(.*)$ $1? [cookie=language:%1:.example.com,env=language:%1,R]
SetEnv prefer-language $language
The problem is with the last line - The value is always set to empty. It works if I hardcode it, but not if I try to refer to a variable. Is there some special syntax to refer to environment variables in this context, or is there some other way to set prefer-language?
Edit: Cross-posted to Apache users list.
You can set environment variables with mod_rewrite as well. Actually, you already did that (see env/E flag).
I can’t test it with mod_negotiation myself, but the following should work and set the prefer-language:
RewriteCond %{QUERY_STRING} ^((?:[^&]&)*)language=(en|fr|no)&?([^&].*)?$
RewriteRule ^ %{REQUEST_URI}?%1%3 [L,CO=language:%2,R]
RewriteCond %{HTTP_COOKIE} (^|[,\s])language=([^\s,;]+)
RewriteRule ^ - [L,E=prefer-language:%2]
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1
But it would be far easier if you put the language identifier into the URL path like /en/…:
SetEnvIf Request_URI ^/(en|fr|no)/ prefer-language=$1
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1
I don’t know if you need the additional/second SetEnvIf variable.
Looks like there's no support for variables in SetEnv, but here's a working configuration if someone else is trying to do the same. It's a simpler kind of language selection, since it just copies the language parameter from the referer to the current URL if it's not changed:
RewriteEngine On
RewriteBase /
# Keep the language parameter if specified in the last URL
RewriteCond %{HTTP_REFERER} ^(?:.*[&?])?language=(en|fr|no).*$
RewriteCond %{QUERY_STRING} !^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^(.*)$ $1?language=%1 [redirect=permanent]
# Set the language from the URL parameter
RewriteCond %{QUERY_STRING} ^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^ - [env=prefer-language:%1]
# Cache only when the language parameter is set
<IfDefine !prefer-language>
Header set Vary *
</IfDefine>