Search code examples
apache.htaccessmod-rewriteurl-rewriting

Apache 2.4 URL Rewrite: /server/?Server=ServerName to /server/ServerName


I am trying to simply rewrite the URL to /server/ServerName from /server/?Server=ServerName so that the ServerName parameter is passed to PHP.

I current have this in my .htaccess file:

RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} Server=([^&]+)
RewriteRule "^server/$" "/server/%1/?"

When attempting to view both /server/ServerName or /server/?Server=ServerName I get a 404 error.

Here is my rewrite log:

init rewrite engine with requested uri /server/
pass through /server/
strip per-dir prefix: C:/wamp64/www/server/ -> server/
applying pattern '^server/$' to uri 'server/'
RewriteCond: input='Server=ServerName' pattern='Server=([^&]+)' => matched
rewrite 'server/' -> '/server/ServerName/?'
split uri=/server/ServerName/? -> uri=/server/ServerName/, args=<none>
trying to replace prefix C:/wamp64/www/ with /
trying to replace context docroot C:/wamp64/www with context prefix 
internal redirect with /server/ServerName/ [INTERNAL REDIRECT]

At this point, I need a little direction because I'm frustrated and I feel like it's a simple thing I am missing.

I've attempted tweaks from:

I have also been interating on the rewrite code in attempts to see if it was actually rewriting.

Using the code below successfully rewrites the directory /test2/ to /server/?Server=ServerName and the page loads fine so I know the module is active and functioning.

RewriteRule ^test2/$ /server/?Server=ServerName [PT,L,R=301]

Attempted this change with no luck. URL doesn't rewrite, but the page loads. Apache 2.4 .htaccess friendly URL rewrite

RewriteRule ^server/([^/\.]+)/?$ /server/?Server=$1? [L]

Solution

  • rewrite the URL to /server/ServerName from /server/?Server=ServerName:

    RewriteCond %{QUERY_STRING} Server=([^&]+)
    RewriteRule "^server/$" "/server/%1/?"
    

    You seem to have this the wrong way round. You should be linking to /server/ServerName in your HTML source and therefore internally rewriting the request from /server/ServerName to /server/index.php?Server=ServerName (note the addition of index.php, as clarified in comments). /server/index.php?Server=ServerName is the underlying (hidden) file-path that actually handles the request.

    Although you seem to have it about right in your last line...

    URL doesn't rewrite, but the page loads.

    RewriteRule ^server/([^/\.]+)/?$ /server/?Server=$1? [L]
    

    The URL must be rewriting, otherwise the page would not load. There may be some confusion as to what a "rewrite" actually is. This does not change the URL. You do not use .htaccess to change the URL. You must change the URL manually in your HTML source - the URL you are linking to.

    You can (optionally) implement an external "redirect" later if you wish - this does change the URL. But this is only to redirect search engines and 3rd parties that might have linked to or indexed the old URLs. So, this is for SEO, not to make your application "work".

    So, in summary, in this order:

    1. Change the URL in your HTML source so you are linking to URLs of the form /server/ServerName.
    2. (OPTIONAL) If you are changing an existing URL structure then redirect any direct request to /server/?Server=ServerName (or /server/index.php?Server=ServerName) to /server/ServerName (the canonical URL).
    3. Internally rewrite the request from /server/ServerName (the canonical URL / the URL you are linking to) to /server/index.php?Server=ServerName (the underlying file that handles the request).

    In the root .htaccess file:

    RewriteEngine On
    
    # (OPTIONAL) For SEO, if changing an existing URL structure...
    # Redirect "/server/?Server=ServerName" to "/server/ServerName"
    RewriteCond %{QUERY_STRING} ^Server=([^&./]+)(&|$) [NC]
    RewriteRule ^server/(index\.php)?$ /server/%1 [NE,R=301,L]
    
    # Rewrite request from "/server/ServerName" to "/server/index.php?Server=ServerName"
    RewriteRule ^server/([^/.]+)$ server/index.php?Server=$1 [END]
    

    This assumes you are on Apache 2.4 in order to be able to use the END flag in the last rule. This avoids having to have an additional condition in the first rule that checks for a direct request, and not a "rewritten" request (to avoid a redirect loop).

    In the first rule (the "redirect") the index.php part is optional. The %1 backreference contains the value of the Server URL parameter captured in the preceding condition. The Server URL param must be non-empty and not contain dots or slashes (as per the regex you gave in the last rule), otherwise it is not redirected or rewritten. Note that a literal dot in a regex character class does not need to be backslash-escaped.

    Note that I have assumed (as per your example) that the URL being requested does not end in a trailing slash (ie. /server/ServerName and not /server/ServerName/), so I have removed the optional /? at the end of the RewriteRule pattern in the last rule. Although your log extract would appear to suggest otherwise? If you did need to allow both trailing slash and non-trailing slash URLs then this should be implemented as a separate "redirect" in order to canonicalise the URL, not as part of the "rewrite" that would otherwise promote duplicate content (the slashed and slashless URLs are different URLs).

    Depending on the values you are expecting in the Server URL parameter value, the NE (noescape) flag may or may not be necessary. The QUERY_STRING server variable is already URL-encoded.

    You do not need to use the PT (passthrough) flag in .htaccess, since that is the default behaviour in this context. (The PT flag is only relevant when using mod_rewrite in a server or virtualhost context.)