Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

It is always preferred on a personal website to use relative paths in anchors so that you can easily move your directory structure to a new website, but I want to make part of my website password protected (using .htaccess) and hence use https. Is there a way in an anchor's href to specify a different protocol without hard-coding the www.domain.com as well?

Example:

<a href="/student/example">Link</a>

I want to turn it into something like:

<a href="https: /student/example">Link</a>

The above obviously doesn't work. Is there any way to do it? I am trying to avoid any scripting but would appreciate a JavaScript more than PHP or ASP.

share|improve this question
Welcome to StackOverflow. This is a good question. – Paulpro Jun 12 at 0:27

4 Answers

You should add the https to the specific URLs of your site using .htaccess as well. Make sure your .htaccess file includes this line:

RewriteEngine on

Then try adding this line after it:

RewriteRule "^/student(/.*)" "https://%{HTTP_HOST}$1" [R=301,L]

http://www.askapache.com/htaccess/ssl-example-usage-in-htaccess.html#redirect-urls-to-ssl

share|improve this answer
This will add an extra HTTP request, and will not work the the particular resource is able to be served up using both HTTP and HTTPS (It prevents access to the resource over HTTP). If the resource is only supposed to be accessed over HTTPS then something like the above which blocks access via HTTP is necessary. – Paulpro Jun 12 at 0:23
Just noticed this is your first answer on Stack Overflow. I should definitely be more welcoming :S. Welcome to Stack Overflow! :) – Paulpro Jun 12 at 0:23

You can't do this without relying on Javascript to dynamically change the href. The way the relative URIs are transformed into absolute URIs is described in RFC 3986 Section 5.2.2:

if defined(R.scheme) then
   T.scheme    = R.scheme;
   T.authority = R.authority;
   T.path      = remove_dot_segments(R.path);
   T.query     = R.query;
else
   if defined(R.authority) then
      T.authority = R.authority;
      T.path      = remove_dot_segments(R.path);
      T.query     = R.query;
   else
      if (R.path == "") then
         T.path = Base.path;
         if defined(R.query) then
            T.query = R.query;
         else
            T.query = Base.query;
         endif;
      else
         if (R.path starts-with "/") then
            T.path = remove_dot_segments(R.path);
         else
            T.path = merge(Base.path, R.path);
            T.path = remove_dot_segments(T.path);
         endif;
         T.query = R.query;
      endif;
      T.authority = Base.authority;
    endif;
    T.scheme = Base.scheme;
  endif;
  T.fragment = R.fragment;

Where R is the relative URL and T is the target.

The above basically says that if the scheme is specified in the relative URI, then the target uri will be the entire relative uri, so the only way to specify the scheme is to specify the entire url.

If you want to go with a Javascript based approach you can dynamically set the href using something like: a.href = 'https://' + window.location.host + a.getAttribute('href'). Where a is your AnchorElement.

Here is a demo of the Javascript version: http://jsfiddle.net/7DWV5/

However, largely for the reason you've encountered, it is a good idea to either store your hostname in a config file, or detect it from the HTTP Request Host header in a front controller. That way you can just template it in to your HTML while generating the page. That saves you from having to use client-side scripts to fix your urls after they've been generated, which may be desirable, because not everyone has Javascript enabled.

share|improve this answer

In JavaScript you could do something like:

<script>
function handleLink(a){
    var path = a.getAttribute('href'),
        host = location.hostname;
    location.href = 'https://'+host+path;
    return false;
}
</script>
<a href="/student/example" onclick="return handleLink(this)">Link</a>

I wouldn't though. If you're keen to keep the user on SSL, I'd have the page redirect to an SSL page in the first place

share|improve this answer

I think that there is no "simple" solution... And javascript seems to be a bad idea for such purposes.

You could try:

<base href="https://yourdomain.com/">

placed in document header.

OR

yours idea:

<a href="/test-me1/">regular link 1</a>
<a href="/test-me2/">regular link 2</a>
<a href="/https/test-me3/">secure link</a>

and in the bottom, but before closing body tag place something like this:

<script type="text/javascript">
(function(){

    var h = 'yourdomain.com';
    /* could be replaced with something like window.location.host */

    var a =  document.links;

    for (var c = 0; c < a.length; c++) {

        var i = a[c].href.indexOf('/https/');

        if(-1 !== i)
        {
            a[c].href = 'https://' + h + '/' + a[c].href.substring( i + 7 );
            /* where 7 is a length of '/https/' */
        }
    }
})();
</script>

OR even simply:

<script type="text/javascript">
(function(){

    var a = document.links;

    for (var c = 0; c < a.length; c++) {

        if(-1 !== a[c].href.indexOf('/https/') )
        {
            a[c].href = a[c].href.replace('/https/','').replace('http:','https:');
        }
    }
})();
</script>
share|improve this answer
Again, javascript is not good idea for such purposes. (could be basically turned off or not supported, etc). @Paulpro is right, better to make your https urls server side. – Chris Jun 12 at 2:21
Another idea is to use protocol relative url in base tag. – Chris 2 days ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.