.Htaccess Rewrite: Subdomain as Get Var and Path as Get Var

.htaccess rewrite: subdomain as GET var and path as GET var

Use the first rule to add the subdomain parameter, without changing the URI, then use the 2nd rule to route the URI to index.php:

RewriteEngine On

# Parse the subdomain as a variable we can access in PHP, and
# run the main index.php script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} !^www
RewriteCond %{HTTP_HOST} ^([^\.]+)\.([^\.]+)\.([^\.]+)$
RewriteRule ^(.*)$ /$1?subdomain=%1

# Map all requests to the 'path' get variable in index.php
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [L,QSA]

The second rule needs to have the QSA flag, otherwise the first rule's query string gets lost.

Wildcard .htaccess rewrite subdomain to a subdirectory with subdomain as GET variable

Try this (if you already have some other rewrite rules, put these on top):

RewriteCond %{HTTP_HOST} ^((?!www\.)[^.]+)\.example\.com$
RewriteRule ^ http://example.com/subdomains%{REQUEST_URI}?user=%1 [QSA,L,P]

.htaccess rewrite: subdomain as GET parameter and filepath afterdomain intact

You can use this code in your root .htaccess:

DirectoryIndex index.php
RewriteEngine On

# Parse the subdomain as a variable we can access in PHP, and
# run the main index.php script
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^(?:www|mpmain) [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.[^.]+\.[^.]+$
RewriteRule ^(.*)$ $1?subdomain=%1 [L,QSA]

.htaccess rewrite a subdomain with a variable

Sure that is possible. But you need to tell a few things apart:

The actual host name in the URL ("subdomain") is not part of the path a RewriteRules pattern is internally matched against. You need to use a RewriteCond to access that information:

RewriteEngine on

RewriteCond %{HTTP_HOST} ^(?:www\.)?whatever\.example\.com$
RewriteRule ^ /file.php?var=1 [L,QSA]

RewriteCond %{HTTP_HOST} ^(?:www\.)?whatever1\.example\.com$
RewriteRule ^ /file.php?var=2 [L,QSA]

A typical variant would be to hand over an actual name instead of a numeric value. Here the GET variable would become v=whatever or v=whatever1:

RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTP_HOST} ^(?:www\.)?([^.]+)\.example\.com$
RewriteRule ^ /file.php?var=%1 [L,QSA]

This assumes that all hosts/subdomains are served from by same http server, of course, since it is an internal rewrite.

In general I would recommend that you take a look at the documentation of the tools you want to use. That documentation is, as typical for OpenSource software, of excellent quality and comes with great examples: https://httpd.apache.org/docs/current/mod/mod_rewrite.html

.htaccess - Subdomain and path as GET var

Replace your 2 rules by these 2 rules:

# Map all requests to the 'path' get variable in dispatcher.php
RewriteCond %{HTTP_HOST} !^www [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.[^.]+\.[^.]+$
RewriteRule ^/?$ /dispatcher.php?subdomain=%1 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^www [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.[^.]+\.[^.]+$
RewriteRule ^(.+)$ /dispatcher.php?subdomain=%1&path=$1 [L,QSA]

Mod Rewrite Subdomain to PHP with GET variable

You must capture the first part of the domain in a RewriteCond and then use this in a RewriteRule. The additional RewriteConds are there to prevent www.mydomain.com and index.php being rewritten

RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{REQUEST_URI} !index\.php
RewriteCond %{HTTP_HOST} ^(.+?)\.mydomain\.com$
RewriteRule .* /index.php?username=%1 [L]

But this is only a small part of the needed functionality. Additionally, you must setup DNS entries for all of your username.mydomain.com domain names or setup a wildcard DNS entry *.mydomain.com pointing to your host.

Otherwise, the client tries to contact jcraine.mydomain.com, for example, and doesn't find a DNS entry and complains.

If this is a virtual host, you must also add a ServerAlias for each of your usernames

ServerAlias jcraine.mydomain.com

or a wildcard catching all subdomains

ServerAlias *.mydomain.com

Rewrite subdomain and URL-path to URL parameters but allow access to files

If your URLs don't contain dots then exclude dots from your regex - this naturally excludes real files (that contain a dot before the file extension). This avoids the need for a filesystem check.

Your script should handle /index.php?lang=%1 and /index.php?lang=%1&page= exactly the same, so the first rule is superfluous.

RewriteRule ^index\.php$ - [L]

This rule should be first, not embedded in the middle.

Try the following instead:

RewriteRule ^index\.php$ - [L]

RewriteCond %{HTTP_HOST} ^((?!www).+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page=$1 [QSA,L]

RewriteRule ^([^.]*)$ /index.php?page=$1 [QSA,L]

Your last rule that rewrites everything else to index.php, less the lang URL param is questionable. Why not just include this in the preceding rule and validate the language in your script? Which you need to do anyway.

Assuming there is always a subdomain, then your rules could then be reduced to:

RewriteRule ^index\.php$ - [L]

RewriteCond %{HTTP_HOST} ^(.+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page=$1 [QSA,L]

Requests for the www language are then validated by your script and defaulted accordingly, as if the lang param was not passed at all (which you need to be doing anyway).

If your subdomain is entirely optional and you are accessing the domain apex then make it optional (with a non-capturing group) in the regex:

RewriteCond %{HTTP_HOST} ^(?:(.+)\.)?example\.com [NC]
:

The lang param would then be empty if the domain apex was requested.

(Bonus) en.domain.com/hello/there/sir -> index.php?lang=en&page=hello&sub1=there&sub2=sir

It would be preferable (more efficient, flexible, etc) to do this in your PHP script, not .htaccess.

But in .htaccess you could do something like this (instead of the existing rule):

:
RewriteRule ^([^/.]*)(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?$ /index.php?lang=%1&page=$1&sub1=$2&sub2=$3&sub3=$4&sub4=$5 [QSA,L]

The URL params are empty when that path segment is not present.

It is assumed the URL-path does not end in a slash (the above will not match if it does, so a 404 will result). If a trailing slash needs to be permitted then this should be implemented as a canonical redirect to remove the trailing slash. Or reverse the logic to enforce a trailing slash.

This particular example allows up to 4 additional "sub" path segments, eg. hello/1/2/3/4. You can extend this method to allow up to 8 (since there is a limit of 9 backreferences in the Apache syntax) if required. Any more and you will need to use PHP. (You could potentially handle more using .htaccess, but it will get very messy as you will need to employ additional conditions to capture subsequent path segments.)



I tried adding RewriteCond %{REQUEST_FILENAME} !-f to respect local files but that breaks the whole file it seems

That should also be sufficient (if dots are permitted in your URLs). But I wonder where you were putting it? It should not "break" anything - it simply prevents the rule from being processed if the request does map to a file - the rule is "ignored".

This is of course assuming you are correctly linking to your resources/static assets using root-relative (starting with a slash) or absolute (starting with scheme + hostname) URLs. If you are using relative URLs then they will probably result in 404s. If this is the case then see my answer to the following question on the Webmasters stack:

  • https://webmasters.stackexchange.com/questions/86450/htaccess-rewrite-url-leads-to-missing-css

htaccess rules to rewrite subfolder to a GET variable

This should do it for you:

RewriteEngine on
RewriteCond %{HTTP_HOST} =sub.example.com
# Following condition added to support changed requirement, see comments
RewriteCond %{QUERY_STRING} !(?:^|&)var=
RewriteCond %{REQUEST_URI} !^/admin/
RewriteRule ^(.*)$ http://www.example.com/?var=$1 [R=301,L]

This will drop any query string that was in the original request. If you want to keep any query string, and just append 'var=...' to it, then add QSA to the flags at the end of the last line, separated by a comma.

Rewrite subdomain to subdirectory in Apache .htaccess file

RewriteCond %{HTTP_HOST} ^office.example.com$
RewriteRule ^(.*)$ https://example.com/office/$1 [L,NC,QSA]

Rather confusing, this should implicitly trigger an external 302 (temporary) redirect, not an internal rewrite - when specifying a different host in the substitution string to the one being requested. (Although in my experience, any absolute URL in the substitution string triggers an external redirect.)

If it does trigger an internal rewrite (as indicated by the logs) then the requested hostname does not change (since this is not a separate request) and you will indeed get a rewrite loop.

However, if "the subdomain is an alias of the main domain" and a rewrite is what's required, then there is no need to specify a hostname in the substitution string and you will indeed need to make additional checks to prevent an internal rewrite loop (500 error).

Try the following instead:

RewriteEngine on

RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteRule !^office office%{REQUEST_URI} [L]

...to exclude any requests (including rewritten requests) that already start /office.

No need for the NC and QSA flags.

Alternatively, to only target direct requests (not rewritten requests) you could check the REDIRECT_STATUS environment variable instead (which is empty on the initial request and set to "200", as in 200 OK, after the first successful rewrite).

For example:

RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) office/$1 [L]

This has the added "benefit" that you can potentially have a sub-subdirectory called /office as well. ie. /office/office.

UPDATE: A third version is to check against the REQUEST_URI server variable. However, I would not expect this to be any different from the first version above.

RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{REQUEST_URI} !^/office
RewriteRule ^ office%{REQUEST_URI} [L]

Sadly enough, both your suggestions gave the same error as before.

Two things to try...

  • Add a slash prefix on the substitution string. ie. /office%{REQUEST_URI} and /office/$1 respectively. This changes the substitution string into a URL-path, rather than a relative filesystem path. However, I wouldn't necessarily expect this to make any difference in this respect. (It would be required for an external redirect.)

  • Use the END flag instead of L on the RewriteRule directives - this is an Apache 2.4 addition that should halt all processing. The L flag "only" ends the current pass before restarting the rewriting process (hence the need for additional checks to prevent rewrite loops).

But now any other file (IMG, CSS) gives an 404.

The above rewrites everything, so it will naturally rewrite all static resources if they don't already start /office. (If they already start /office then they should already be excluded by the above rules.)

To exclude common resources, you could make an exception (an additional RewriteCond directive) to exclude specific file extensions. For example:

RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif)$

And/or add an additional RewriteCond directive to exclude requests that already map to physical files (although this is "marginally" more expensive). For example:

RewriteCond %{REQUEST_FILENAME} !-f

Summary:

RewriteEngine On

RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) office/$1 [END]


Related Topics



Leave a reply



Submit