Forum Moderators: phranque

Message Too Old, No Replies

Redirect to https for specific page only

         

HDClown

3:28 am on Jan 28, 2016 (gmt 0)

10+ Year Member



I need to redirect to HTTPS based on a specific match to a page name: apply.php

apply.php may occur at the root or in subdirectories, and it may or may not also have URL parameters after it.

Some examples of possible URLs would be:
  • http://www.domain.com/apply.php
  • http://www.domain.com/apply.php?parm1=ABC
  • http://www.domain.com/user/apply.php
  • http://www.domain.com/user/apply.php?parm1=ABC

    In any situation such as this, as long as the page apply.php is in the URL, then it should redirect to HTTPS.

    The original URL does not need to be modified, other than the change to HTTPS, and no other pages should be redirected to HTTPS.

    is something like thus on the right track?


    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^apply.php https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
  • whitespace

    10:41 am on Jan 28, 2016 (gmt 0)

    10+ Year Member Top Contributors Of The Month



    Yes, that's on the right track. However, you need to look at every character and ask yourself what it means... in the RewriteRule pattern (ie. "^apply.php") what do the characters ^ (caret) and . (dot) mean?

    HDClown

    12:48 pm on Jan 28, 2016 (gmt 0)

    10+ Year Member



    Here is a revised one. This seems to be working as expected.


    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ([^/]+)?apply\.php https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]


    Do I have anything wrong/bad about this?

    whitespace

    2:37 pm on Jan 28, 2016 (gmt 0)

    10+ Year Member Top Contributors Of The Month



    RewriteRule ([^/]+)?apply\.php


    The ([^/]+)? part of the pattern is superfluous and can simply be omitted. Since "apply.php" should always be at the end of the URL-path then you should probably include an end-of-string anchor also. So we have:


    RewriteRule apply\.php$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]


    Note also that SERVER_NAME will contain the hostname as supplied by the client (ie. HTTP_HOST) unless UseCanonicalName is "On". Do you already have a canonical www redirect?

    HDClown

    4:12 pm on Jan 28, 2016 (gmt 0)

    10+ Year Member



    I wasn't sure if putting the end-of-string anchor would mean that it would not match when URL parameters are used (ie. apply.php?param=ABC) but I tested it and it is working fine.

    I was thinking that with ([^/]+)? I would avoid any potential odd recursion issues by making sure it was checking for apply.php in the root or a subdirectory, but to be honest, wasn't sure if that's really what the regex was determining. I suppose that if I'm using the end-of-string anchor, that should avoid any problems.

    I have a base to www redirect but I don't know if UseCanonicalName is On. This is GoDaddy cPanel Shared Hosting w/Dedicated IP.

    Using the following in .htaccess at the site root, everything looks to be performing as expected, as best as I can test.

    RewriteEngine on
    RewriteBase /

    RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]

    RewriteCond %{HTTPS} off
    RewriteRule apply\.php$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

    whitespace

    6:38 pm on Jan 28, 2016 (gmt 0)

    10+ Year Member Top Contributors Of The Month



    I wasn't sure if putting the end-of-string anchor would mean that it would not match when URL parameters are used (ie. apply.php?param=ABC) but I tested it and it is working fine.


    The RewriteRule pattern only matches against the URL-path (less the directory-prefix). This notably excludes the query string. If you needed to match against the query string then you would need to use a separate RewriteCond directive and check against the %{QUERY_STRING} server variable.

    I was thinking that with ([^/]+)? I would avoid any potential odd recursion issues by making sure it was checking for apply.php in the root or a subdirectory...


    Well, [^/]+ would only match the first path segment when "apply.php" was in a subdirectory, this excludes the case when "apply.php" is in the document root or is in a sub-subdirectory. However, the trailing ? then makes it all optional - so it does match document root and sub-subdirectory files after all. Basically, it matches anything and everything, which is what regular expressions do anyway (when you don't have an anchor).

    I have a base to www redirect but I don't know if UseCanonicalName is On.


    Since you have your www redirect first, in which you are explicitly stating the hostname, I don't think it really matters.

    Btw, the RewriteBase directive is not required here. This only affects relative path substitutions (in the RewriteRule) - you don't have any.

    lucy24

    10:50 pm on Jan 28, 2016 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    the RewriteBase directive is not required here. This only affects relative path substitutions

    I experimented with this once. (Documentation is good. A test site is better.) The RewriteBase directive only applies in internal rewrites, not external redirects, and then only when the target doesn't already start in /. If you form the habit of beginning all your targets in / for root (or in http etcetera, duh, in the case of redirects) then the RewriteBase doesn't matter anyway. Note that / in the target always refers to the site root, regardless of where the current RewriteRule is located. (^ in the pattern does depend on what directory you're in.)

    Incidentally: Surely you don't have this same page name in multiple domains living on the same server? If you don't, you should proceed directly to https://example.com in the target. It's always better to spell things out explicitly, when possible, rather than ask the server to dredge up information from some other source.

    I'm not sure if %{REQUEST_URI} is faster or slower than %1 referring to a capture in a RewriteCond. (You'd put it in a Condition because it's a complicated capture and the vast majority of requests won't require the redirect.)

    whitespace

    10:04 am on Jan 29, 2016 (gmt 0)

    10+ Year Member Top Contributors Of The Month



    The RewriteBase directive only applies in internal rewrites, not external redirects, ...


    It applies to external redirects as well (providing the substitution path is relative - ie. doesn't start with a slash or protocol name). In fact, in this case (external redirect + relative substitution), the RewriteBase directive would be mandatory (otherwise the directory-prefix is added and the redirect would most probably break). Although using relative paths for external redirects is best avoided to begin with.

    lucy24

    9:48 pm on Jan 29, 2016 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    :: detour to test site for various experiments ::

    wtf? Don't the Apache docs clearly and unambiguously say that the default value for RewriteBase is / for root? Somewhere along the line they seem to have lost track of this detail and are instead trying to send me up a physical directory path. (Hm. It can't possibly have anything to do with test site's IPv6 address, can it? I'm pretty sure I did the original RewriteBase experimenting back when the site was IPv4.)

    :: further mystification as I see that logs have now decided to give my IPv4 address instead of the IPv6 they'd been using ever since I made it an IPv6 site, and it isn't because my ISP has changed something ::

    In any case I think we can all agree that if you use an absolute target-- starting in either / or protocol-plus-domain, depending-- there is no chance of nasty surprises.

    whitespace

    3:23 pm on Feb 1, 2016 (gmt 0)

    10+ Year Member Top Contributors Of The Month



    Don't the Apache docs clearly and unambiguously say that the default value for RewriteBase is / for root?


    Well, in a server/VirtualHost context, a relative substitution is likely* to be seen as a URL-path relative to the document root - so in a sense that is like a RewriteBase / directive, although RewriteBase itself does not apply in a server context.

    (* unless the substitution happens to exist as a physical directory in the root of the filesystem then it will be seen as a file-system path relative to the filesystem root!)

    Somewhere along the line they seem to have lost track of this detail and are instead trying to send me up a physical directory path.


    In a per-directory context the directory-prefix (the physical directory path to the .htaccess file) is added back to relative substitutions. RewriteBase (which defaults to None) needs to be explicitly stated in order to change this. Hasn't this always been the case?

    But yes, if you don't use relative paths then none of that matters anyway.

    lucy24

    9:51 pm on Feb 1, 2016 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



    :: detour to Apache docs ::

    Default: None

    ###. Then where, exactly, did I get the idea the default is / ? I could swear I've been reading it right here for years. It isn't a recent change; I checked back to 2.0 and even dredged up 1.3 in case it's one of those outdated rules (like "preheat the oven") that people have just been passing along mechanically.

    :: counting on fingers ::

    The line
    RewriteBase /
    takes up 14 or 15 bytes depending on platform. I doubt most people have that many internal rewrites, so we don't even need to argue about which form is more economical ;)