Tag: mod_headers

  • Enabling Cross-Origin Resource Sharing CORS for Apache

    Enabling Cross-Origin Resource Sharing CORS for Apache

    When trying to share resources across different domains (host-a.com vs. host-b.com) you will come across the concept of Cross-Origin Resource Sharing (CORS). In order to be able to share resources across different domains you will most likely need to enable to CORS manually on your server. For instance, when a script on host-a.com tries to access resources on host-b.com CORS needs to be enabled on host-b.com. This post shows you the steps needed for enabling Cross-Origin Resource Sharing CORS for Apache using a .htaccess file.

    Note: Looking for a way to enable CORS for PHP? Have a look at Enabling Cross-Origin Resource Sharing CORS for PHP.

    Prepare your .htaccess

    In order to to enable CORS on Apache you need mod_headers and mod_setenvif. The example below show you how to prepare Apache for the two types of CORS requests:

    1. Pre-Flight Requests
    2. Simple Requests

    Pre-Flight Requests are generated on the client side when not using GET, POST and HEAD requests on external domain resources (or setting custom headers). In this case we need to check Access-Control-Allow-Headers and Access-Control-Allow-Methods in order to allow or disallow CORS requests to our server. Second, simple requests handle GET, POST and HEAD requests across different domains. In this case we need to check the Origin header and set Access-Control-Allow-Origin correspondingly to allow such CORS requests. Below you find examples to allow CORS for method-a Pre-Flight Requests and simple requests from host-a.local or host-b.local, optionally for accessing different remote scripts too (e.g. https://host-b.local/method-a.php).

    
    
       ##########################################################################
       # 1.) ENABLE CORS PRE-FLIGHT REQUESTS
       # e.g. PUT, DELETE, OPTIONS, ...
       # we need to set Access-Control-Allow-Headers and 
       # Access-Control-Allow-Methods for allowed domain(s)
       ##########################################################################
       
       # first check for pre-flight headers and set as environment variables
       # e.g. header method-a is set here
       SetEnvIf ^Access-Control-Request-Method$ "method-a" METHOD_A
       SetEnvIf ^Access-Control-Request-Headers$ "^Content-Type$" HEADER_A
    
       # set corresponding response pre-flight headers for allowed domain(s)
       Header set Access-Control-Request-Methods "method-a" env=METHOD_A
       Header set Access-Control-Request-Headers "content-type" env=HEADER_A
       
       # TODO: add allowed additional pre-flight requests here...
       
       #########################################################################
       # 2.) ENABLE CORS *SIMPLE REQUESTS* (vs. Pre-Flight Requests from above)
       # e.g. GET, POST and HEAD requests
       # we need to set Access-Control-Allow-Origin header for allowed domain(s)
       # also note that POST requests need to match one of the following 
       # Content-Type: 
       # 1) application/x-www-form-urlencoded
       # 2) multipart/form-data
       # 3) text/plain
       #########################################################################
       
       # write line for each domain you would like to enable CORS requests for
       # e.g. origin = http://host-a.local or http://host-b.local 
       SetEnvIfNoCase Origin "((http(s?))?://(www\.)?(host\-a|host\-b)\.local)(:\d+)?$" AccessControlAllowOrigin=$0
       Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
       
       # e.g. origin = https://host-b.local/method-a.php
       SetEnvIfNoCase Origin "https://host-b.local/method-a.php" AccessControlAllowOrigin=$0
       Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
       
       # generic regexp match for more flexibel use cases
       #SetEnvIfNoCase Origin "((http(s?))?://(www\.)?(host\-a|host\-b)\.local)(:\d+)?$" AccessControlAllowOrigin=$0
       #Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
     
       # TODO: add additional allowed simple requests here...
     
    
    

    Test File

    In case you want to test this CORS setup here’s a simple test file:

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script><script>// <![CDATA[
    function a() {
    var jqxhr = $.get( "http://host-b.local", function() {
    })
    .done(function() {
    alert( "second success" );
    })
    .fail(function() {
    alert( "error" );
    })
    }
    
    function b() {
    var jqxhr = $.get( "http://host-b.local/method-b", function() {
    })
    .done(function() {
    alert( "second success" );
    })
    .fail(function() {
    alert( "error" );
    })
    }
    // ]]></script><a>Host B (GET)</a> <a>Host B / Method A (GET)</a>

    Be sure to configure your Apache VHost settings accordingly.

    Improvements

    Since we don’t want to manually edit .htaccess files a simple configuration script would be nice to set domain configurations automatically for CORS enabled domains/methods.