Openstreetmap tiles over https with openlayers and server redirect

Good news: Redirect from https to http works for tiles with openlayers. This prevents mixed mode warning in Internet Explorer

I recently got some problems on a https site. I included a map from openstreetmap.org and the Internet Explorer started complaining about mixed content. Btw. it is very annoying, that for IE7 you have to click YES on the dialog, and for IE8 you have to click NO.

The openlayers javascript files come from my https server so they are no problem. The only remaining reason for this were that the tiles coming from the openstreetmap server over http. After some tries with proxying the tiles over a php script, which was too slow, finally the solution was so easy.
Writing a little tiles.php which just redirects to openstreetmap instead of proxying, and complaints from IE stopped, as the tiles.php is on the https site:

$x = intval($_GET['x']);
$y = intval($_GET['y']);
$z = intval($_GET['z']);
$r = strip_tags($_GET['r']);
if(empty($r)) $r="mapnik";
$server = array();
switch ($r) {
    case 'mapnik':
        $server[] = 'a.tile.openstreetmap.org';
        $server[] = 'b.tile.openstreetmap.org';
        $server[] = 'c.tile.openstreetmap.org';

        $url = 'http://' . $server[array_rand($server)];
        $url .= "/" . $z . "/" . $x . "/" . $y . ".png";
        break;

    case 'osma':
    default:
        $server[] = 'a.tah.openstreetmap.org';
        $server[] = 'b.tah.openstreetmap.org';
        $server[] = 'c.tah.openstreetmap.org';

        $url = 'http://' . $server[array_rand($server)] . '/Tiles/tile.php';
        $url .= "/" . $z . "/" . $x . "/" . $y . ".png";
        break;
}

header("HTTP/1.1 301 Moved Permanently");
header("Location: $url");
exit();

The openlayers layer now just has to point to this little redirection and everything is fine:

layerMapnik = new OpenLayers.Layer.OSM("Mapnik","tiles.php?z=${z}&x=${x}&y=${y}&r=mapnik");

Inspired by http://wiki.openstreetmap.org/wiki/ProxySimplePHP

Advertisements

, ,

  1. #1 by gisfiend on December 2, 2010 - 01:52

    Wow – hours of frustration, and I didn’t even notice that I had to click ‘No’ in IE8. I thought this was a complete bust for me to use HTTPS on my site. Thanks for the post.

  2. #2 by Nicolae Surdu on May 26, 2011 - 10:48

    Doesn’t work on my side. It still complains that some content come from unsecure location. We did it using a direct re-write in NginX, but the result was still a 301 redirect.

    • #3 by gunni on May 26, 2011 - 17:58

      Hmm, for me it does work. I am using the code posted on an apache 2.2. Dont know what the problem is on your site.

  3. #4 by Carlos Krefft on June 22, 2012 - 18:08

    Awesome Thanks!

  4. #5 by Piotr Pelczar on September 9, 2012 - 11:49

    Thanks a lot for solution! But: Executing a php script for many files takes a lot of time and resources for interpreter. Best solution is write a .htaccess file. E.x.:

    RewriteEngine On

    RewriteCond %{QUERY_STRING} z=([0-9]*)&x=([0-9]*)&y=([0-9]*)&r=mapnik
    RewriteRule tiles.php http://a.tile.openstreetmap.org/%1/%2/%3.png? [NC,L,R=301]

    • #6 by gunni on September 9, 2012 - 11:54

      Yes, that would of course be a better solution, but in my case i am not able to use htaccess or rewrite rule because of permissions.
      Thanks anyway for anyone who may have the permissions.

    • #9 by andrewgeddes230 on May 4, 2013 - 06:47

      Can you expound upon your solution a little more? I think that I may have a similar issue but I am not sure how to implement your rewrite rule? Is gunni’s php file still needed with the rewrite rule? Also, wouldn’t three Rewrite rules be needed for http://a.tile… and http://b.tile… and http://c.tile….?

      • #10 by gunni on May 4, 2013 - 10:19

        No. With the rewrite rule the php file wont be needed. I only use it because i have no access to the htaccess files.
        And yes if you use more than one tile server (recommended for load balancing ) there has to be one rule for every server.

  5. #11 by Dan Dascalescu on July 2, 2013 - 22:40

    Here is a redirect block I used for nginx to avoid IE security warnings with Cloudmade maps used from OpenLayers:

    location ~ /r/cloudmadetiles/([a-c])/(.*?)/(.*?)/(.*?)\.png {
    # redirect to cloudmade to avoid IE mixed mode warnings
    return 301 http://$1.tile.cloudmade.com//71401/256/$2/$3/$4.png;
    }

    I then created the OSM object like this:

    var osm_layer = new OpenLayers.Layer.OSM(“OpenStreetMap (Cloudmade)”,
    [
    // “http://a.tile.cloudmade.com/d089e834e3a7405dae259122d0f533d7/71401/256/${z}/${x}/${y}.png”,
    “/r/cloudmadetiles/a/${z}/${x}/${y}.png”,
    “/r/cloudmadetiles/b/${z}/${x}/${y}.png”,
    “/r/cloudmadetiles/c/${z}/${x}/${y}.png”
    ], {
    tileOptions: {crossOriginKeyword: null},
    }
    );

  6. #12 by Spekkio on September 2, 2013 - 13:16

    I modified the code a little, chrome was still complaining but not firefox. Instead I downloaded the file with imagecreatefrompng() and replaced header(“HTTP/1.1 301 Moved Permanently”);
    header(“Location: $url”); with header(‘Content-Type: image/png’); .. I took the LoadPNG() code from http://php.net/manual/en/function.imagecreatefrompng.php

    not sure how much cpu this will take though, I think this will actually encrypt the png’s over https.

    …previous code…
    /*
    header(“HTTP/1.1 301 Moved Permanently”);
    header(“Location: $url”);
    */

    function LoadPNG($imgname)
    {
    /* Attempt to open */
    $im = @imagecreatefrompng($imgname);

    /* See if it failed */
    if(!$im)
    {
    /* Create a blank image */
    $im = imagecreatetruecolor(150, 30);
    $bgc = imagecolorallocate($im, 255, 255, 255);
    $tc = imagecolorallocate($im, 0, 0, 0);

    imagefilledrectangle($im, 0, 0, 150, 30, $bgc);

    /* Output an error message */
    imagestring($im, 1, 5, 5, ‘Error loading ‘ . $imgname, $tc);
    }

    return $im;
    }

    header(‘Content-Type: image/png’);

    $img = LoadPNG($url);

    imagepng($img);
    imagedestroy($img);

    • #13 by gunni on September 2, 2013 - 13:22

      Basicly you just proxy the image. Thats what i wanted to avoid because of performance and is what the original script does http://wiki.openstreetmap.org/wiki/ProxySimplePHP .
      And your code adds additional unneeded code as you can simple proxy the file with readfile like in the original proxy code.

      • #14 by Spekkio on September 2, 2013 - 13:30

        I still had problems with chrome using the redirect method, have you been able to get it working with chrome? I didn’t know about ProxySimple. I’ll look at that instead, I think caching when using this method is a good idea. Thanks 🙂

      • #15 by gunni on September 2, 2013 - 14:56

        Yes i can see the problems in chrome, but dont know yet how to handle this. It works in IE, Firefox and Safari. Maybe i look into it again.

  7. #16 by Alex Ismail on December 7, 2013 - 01:47

    Could someone explain where the following line of code needs to be added:

    layerMapnik = new OpenLayers.Layer.OSM(“Mapnik”,”tiles.php?z=${z}&x=${x}&y=${y}&r=mapnik”);

    I’m using the Openlayers module under Drupal.

    Thank you,
    Alex

    • #17 by gunni on December 7, 2013 - 01:52

      This is just the javascript part where the map layer gets assigned.
      It has the url pointing to the “proxy”.

      • #18 by Alex Ismail on December 7, 2013 - 02:20

        Gunni, thank you for your prompt reply.

        “This is just the javascript part where the map layer gets assigned.”

        Unfortunately, I don’t know to which Javascript file to add the line. Sorry, might be obvious to you but I don’t know where the map layer gets assigned.

      • #19 by Frank Sagurna on December 7, 2013 - 12:32

        This is the line where you define your map. Maybe take a look at a simple map example like this: http://wiki.openstreetmap.org/wiki/Openlayers_Track_example

        Right after the comment

        // Define the map layer // Here we use a predefined layer that will be kept up to date with URL changes

        the map layer gets defined like

        layerMapnik= new OpenLayers.Layer.OSM.Mapnik(“Mapnik”);

        and you should use

        layerMapnik = new OpenLayers.Layer.OSM(“Mapnik”,”tiles.php?z=${z}&x=${x}&y=${y}&r=mapnik”);

        instead if you want to use this “proxy”.

  8. #20 by Aaron on December 17, 2013 - 02:26

    Thank you for this write up. I wrote something like it in python for my environment. It looks like this.

    #!/Python27/python
    #
    # Open Street Map tile redirect. They do not serve in https.
    # This script redirects from https to http, bypassing an Internet Explorer mixed security warning.
    import cgi
    from random import choice
    cgiVars = cgi.FieldStorage()
    z = cgiVars.getvalue(“z”)
    x = cgiVars.getvalue(“x”)
    y = cgiVars.getvalue(“y”)
    server = choice([‘a’,’b’,’c’])
    print “Location: http://%s.tile.openstreetmap.org/%s/%s/%s.png“%(server,z,x,y)
    print # to end the CGI response headers.

  9. #21 by Angel on April 25, 2014 - 19:46

    Hi ,

    Any idea how to do it for iis web server?

    Thanks
    Angel

    • #22 by gunni on April 25, 2014 - 19:57

      No, dont know much about IIs

  10. #23 by Paul on May 25, 2014 - 18:50

    As of February 2014, the tiles URL have been made available over SSL. There is no need for this workaround any longer.

    Solution: Save the OpenLayer.js locally, serve it under SSL and change the URLs of a.tile/b.tile and c.tile within from http to https.

    https://blog.openstreetmap.org/2014/02/11/osm-enhances-user-privacy/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s