Jump to content

Paths when rewriting URLs


NotionCommotion

Recommended Posts

I would like to better understand relative and absolute paths when rewriting URLs.  My virtual host configuration is shown below.

I wish the server to see something like:

https://example.com?page=page1&controller=controller1&data1=123&data2=321

Given the rewrites as shown in my virtual host, what would be the proper URL in the browser?  One of these (note the ? and &), or something different?

https://example.com/page1/controller1?data1=123&data2=321
https://example.com/page1/controller1&data1=123&data2=321

Next, if I enter one of the URLs, how do relative paths to images, etc work?  Would the browser think it is in the root directory, or in /page1/controller1?  I had problems with relative paths, and changed to absolute paths, and it fixed the problem, but I wish to better understand what is happening.

 

On a side note, I would appreciate any critique of my virtual host configuration.  My goal is for all requests to example.com to redirect to https://example.com, for only https://example.com (no subdomain) to redirect to https://www.example.com, and do the rewriting of page and controller.

 

Thank you

# Note that if a virtual ServerName is not found (i.e. IP 192.168.1.200), Apache defaults to first virtual host.
# Note that if ServerName is set to one of the virtual host ServerName's in the Second Section, it doesn't work (why?)

# Handle just example.com to http
<VirtualHost *:80>
    ServerName example.com
    ServerAlias *.example.com
    Redirect / https://www.example.com/
</VirtualHost>

# Handle just example.com without subdomains
<VirtualHost *:443>
    ServerName example.com
    # ServerAlias example.com
    SSLEngine on
    SSLCipherSuite SSLv3:TLSv1:+HIGH:!SSLv2:!MD5:!MEDIUM:!LOW:!EXP:!ADH:!eNULL:!aNULL
    SSLCertificateKeyFile /etc/pki/tls/private/example_key.pem
    SSLCertificateFile /etc/pki/tls/certs/example_startssl.crt
    SSLCertificateChainFile /etc/pki/tls/certs/sub.class1.server.ca.pem
    Redirect / https://www.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias *.example.com
    DocumentRoot /var/www/example/html

    SSLEngine on
    SSLCipherSuite SSLv3:TLSv1:+HIGH:!SSLv2:!MD5:!MEDIUM:!LOW:!EXP:!ADH:!eNULL:!aNULL
    SSLCertificateKeyFile /etc/pki/tls/private/example_key.pem
    SSLCertificateFile /etc/pki/tls/certs/example_startssl.crt
    SSLCertificateChainFile /etc/pki/tls/certs/sub.class1.server.ca.pem

    <Directory "/var/www/example/html">

        allow from all
        Options +Indexes

        <IfModule mod_rewrite.c>

            RewriteEngine On

            RewriteBase /

            # Are these lines necessary, or should I create a virtual host for http on port 80 instead?
            RewriteCond %{HTTPS} !=on
            RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [NE,R,L]

            ## If the request is for a valid directory, file, or link, don't do anything
            RewriteCond %{REQUEST_FILENAME} -d [OR]
            RewriteCond %{REQUEST_FILENAME} -f [OR]
            RewriteCond %{REQUEST_FILENAME} -l
            RewriteRule ^ - [L]

            #remove the trailing slash
            RewriteRule (.+)/$ $1

            # If you add this first rule to support views, be sure to remove the QSA flag from the second rule (maybe not required since the first rule has the L flag)
            #replace mypage/mycontroller with index.php?page=mypage&controller=mycontroller
            RewriteRule ^([^/]+)/([^/]+)/?$ index.php?page=$1&controller=$2 [L,QSA]
            #replace mypage with index.php?page=mypage
            RewriteRule ^([^/]+)/?$ index.php?page=$1 [L,QSA]

        </IfModule>
    </Directory>
</VirtualHost>
Link to comment
Share on other sites

I'll ramble on about a few things.

 

These may be useful to you

http://httpd.apache.org/docs/trunk/urlmapping.html

http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html

 

When you do your rewrite in htacces exclude for if is a file or directory

You must do this before every rewrite rule you need it for

 

not a file

RewriteCond %{SCRIPT_FILENAME} !-f

 

not a directory

RewriteCond %{SCRIPT_FILENAME} !-d
 

The order you write your rewrite rules will matter a lot.

 

apache absolute versus relative

URL-path
    A DocumentRoot-relative path to the resource to be served. Note that mod_rewrite tries to guess whether you have specified a file-system path or a URL-path by checking to see if the first segment of the path exists at the root of the file-system. For example, if you specify a Substitution string of /www/file.html, then this will be treated as a URL-path unless a directory named www exists at the root or your file-system (or, in the case of using rewrites in a .htaccess file, relative to your document root), in which case it will be treated as a file-system path. If you wish other URL-mapping directives (such as Alias) to be applied to the resulting URL-path, use the [PT] flag as described below.

 

Absolute URL
    If an absolute URL is specified, mod_rewrite checks to see whether the hostname matches the current host. If it does, the scheme and hostname are stripped out and the resulting path is treated as a URL-path. Otherwise, an external redirect is performed for the given URL. To force an external redirect back to the current host, see the [R] flag below.

 

 

 

 

lets talk relative, absolute and local urls

 

A path is a slash separated list of directory names followed by either a directory name or a file name.

A directory is the same as a system folder.

 

network-path reference:

If you need to include something on multiple scheme/protocols like both http:// and https://

<script src="//mysite.com/script.js"></script>

if you’re viewing the file local, it’ll try to request with file://

 

relative paths:

hash tag  # (by itself directs to same page, if a fragment is added usually an anchor tag on the same page......but sites have been using them to navigate entire sites or scripts with them over the years)

no identifier (just a directory or file) will append own host

same directory  /

root directory ./

up one directory ../

up two directories ../../

up three directories ../../../

on and on for up directories

 

absolute paths:

any url (more correctly called uri) that includes the protocol and host with optional others following it

 

just a few examples, is way too many to list every possible type.

http://subdomain.domain.tld.sld/directory/file.ext?query=value#fragment

http://subdomain.domain.tld/

http://subdomain.domain.tld.sld/folder/script.php

http://domain.tld/script.php

 

local paths:

sometimes linked when are outside of the www directory

C:\folder\

C:\folder\file

C:/folder/file.ext

\\folder\file

 

If you include the same scripts with the same relative paths above or deeper in folders some are going to break.

The absolute paths will always be the location you specify.

 

You could do some discovery using $_SERVER variables

 

Providing your configuration is correct

<VirtualHost *>
    ServerName mysite.com
    UseCanonicalName on
</VirtualHost>

 

defined in server config

$_SERVER['SERVER_NAME']  mysite.com

 

obtained from the HTTP request header

$_SERVER['HTTP_HOST']  mysite.com

if you used this on a server not using port 80 would also show the port, SERVER_NAME would not

 

$_SERVER['DOCUMENT_ROOT'] /var/www/ , C:/wamp/www

 

$_SERVER['SCRIPT_FILENAME']  /index.php

same path whether it is used in the main file or in an included file

 

host and script

$current_url = filter_var("http://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'], FILTER_SANITIZE_STRING);

 

include the query if exists

if (!empty($_SERVER['QUERY_STRING'])) {
    $query_string = filter_var($_SERVER['QUERY_STRING'], FILTER_SANITIZE_STRING);
    $current_url .= "?" . $query_string;
}

 

onto magic constants

you can do something like this to include files

include_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . ‘database.class.php);

 

 

$_SERVER['SCRIPT_FILENAME'] versus __FILE__

SCRIPT_FILENAME returns the same path whether it is used in the main file or an included file

__FILE__ returns the path of included file if used inside an included file also the path of the main file if was included in that

 

 

To sum it up, you have to figure out which methods best suit your needs and plan it out.

Link to comment
Share on other sites

I'll ramble on about a few things.

 

Wow, you're not kidding!  Thank you.

 

 

When you do your rewrite in htacces exclude for if is a file or directory

You must do this before every rewrite rule you need it for

not a file

RewriteCond %{SCRIPT_FILENAME} !-f

not a directory

RewriteCond %{SCRIPT_FILENAME} !-d

 

Do this before every rewrite rule?  I either misunderstand, or I don't think so.  It is only required once.

 

 

If you need to include something on multiple scheme/protocols like both http:// and https://

<script src="//mysite.com/script.js"></script>

 

Thanks, I did not know that.  So, I could use <script src="//someOneElesesSite.com/script.js"></script>, it it will use the same protocol as which the browser is viewing it?  Nice! Why, however, wouldn't one just use <script src="/script.js"></script> if it was the currently viewed site?

 

 

UseCanonicalName on

 

Never used before.  I will check it out.

 

 

$current_url = filter_var("http://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'], FILTER_SANITIZE_STRING);

 

You know I've never used filter_var().  Thanks! Looks like it will greatly simplify my scripts.

 

 

 

While your post was very helpful, I think it missing the actual main topic of my question.

 

Let's say I enter https://example.com/page1/controller1 into the browser, but directories /page1 is not a directory in the root directory (/var/www/html), but instead, the request is rewritten to https://example.com/index.php?page=page1&controller=controller1 where index.php is located in the root directory.

 

  1. If within index.php, I include the following tag, <img alt="#" src="someImage.png">, will it expect the image to be located in /var/www/html or /var/www/html/page1/controller1?
  2. What is the proper way to add extra GET variables URI https://example.com/page1/controller1 where page1 and controller1 will be rewritten by mod_rewrite as GET variables to index.php?
Link to comment
Share on other sites

 

 

  1. If within index.php, I include the following tag, <img alt="#" src="someImage.png">, will it expect the image to be located in /var/www/html or /var/www/html/page1/controller1?

If you use relative urls path in your HTML it will be added onto the current url. So if your url is https://example.com/page1/controller1 (no / at the end) it will attempt to load the image from https://example.com/page1/ if the url did end with a / then it attempt to load the image from https://example.com/page1/controller1/

 

Personally I always use absolute url paths in my HTML by starting them with a /. Ie  /images/myimage.png will always load the image from http://site.com/images/myimage.png no matter what the current url is.

 

 

 

 

  1. What is the proper way to add extra GET variables URI https://example.com/page1/controller1 where page1 and controller1 will be rewritten by mod_rewrite as GET variables to index.php?

As you normally would by adding by adding them after the ? in the url, eg https://example.com/page1/controller1?var=1&var2=foo. Note in order for these additional parameters to reach index.php you will need to apply the QSA (Query String Append) flag to your RewriteRule

Edited by Ch0cu3r
Link to comment
Share on other sites

That's the default unless you add a different rewrite rule flag that's what it does.

 

The reason I mentioned about the order of the rules.

If for some reason you want to rename a directory or file then you would want it before this rule below

 

You have

RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]

 

The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed

 

My meaning was you may want that for just specific rewrite rules

 

Consider the case when using the S flag

The flag is used to skip rules that you don't want to run.

 

# Is the request for a non-existent file?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# If so, skip these two RewriteRules
RewriteRule .? - [s=2]

RewriteRule (.*\.gif) images.php?$1
RewriteRule (.*\.html) docs.php?$1

Link to comment
Share on other sites

As you normally would by adding by adding them after the ? in the url, eg https://example.com/page1/controller1?var=1&var2=foo. Note in order for these additional parameters to reach index.php you will need to apply the QSA (Query String Append) flag to your RewriteRule

 

Reason I wasn't sure is that https://example.com/page1/controller1 is rewritten to https://example.com?page=page1&controller=controller1, so it would seem https://example.com/page1/controller1?var=1&var2=foo would be rewritten to https://example.com?page=page1&controller=controller1?var=1&var2=foo (two question marks)

 

 

PS.  When posting messages on this forum, how do you prevent the URLs from being displayed as links?

Edited by NotionCommotion
Link to comment
Share on other sites

The QSA flag will merge the two query strings. The rewritten url will become https://example.com/?page=page1&controller=controller1&var=1&var2=foo

 

If you did not apply the QSA flag the var=1&var2=foo query string will be ignored

 

 

PS.  When posting messages on this forum, how do you prevent the URLs from being displayed as links?

Wrap it in nobbc tags or click the Special Tags button and select no parse

Edited by Ch0cu3r
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.