Posted on 5 Comments

Enabling Cross-Origin Resource Sharing CORS for PHP

Source Code Icon

This post is an addition to Enabling Cross-Origin Resource Sharing CORS for Apache to show you how to enable Cross-Origin Resource Sharing CORS for PHP. Thus, in case you don’t have access to the .htaccess you can simply enable CORS for PHP using the following steps.

Setting required headers using PHP

As explained in Enabling Cross-Origin Resource Sharing CORS for Apache you need to make sure that responses to cross-domain requests to your server (e.g. through Ajax requests using jQuery) need to include a set of required headers to be accepted by the client browser. These are

  1. Access-Control-Allow-Origin
  2. Access-Control-Allow-Methods
  3. Access-Control-Max-Age
  4. Access-Control-Allow-Headers

Make sure that Access-Control-Allow-Origin is set a domain value actually allowed by your server. In theory you could use ‘*‘ as well, but some browsers (e.g. Firefox) will simply ignore it and CORS will not work.

PHP code to enable CORS

The following snippet should give you a quick overview about the required HTTP headers to set for CORS to work.

First, it defines a list of allowed origin domains based on regular expressions. This list will be checked against $_SERVER[‘HTTP_ORIGIN’], i.e. the Origin header specified in the client request. If one origin entry from the list matches the required CORS headers will be set. This setup also takes care of the CORS pre-flight request.

// array holding allowed Origin domains
$allowedOrigins = array(
  '(http(s)://)?(www\.)?my\-domain\.com'
);

if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] != '') {
  foreach ($allowedOrigins as $allowedOrigin) {
    if (preg_match('#' . $allowedOrigin . '#', $_SERVER['HTTP_ORIGIN'])) {
      header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
      header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
      header('Access-Control-Max-Age: 1000');
      header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
      break;
    }
  }
}
Posted on 6 Comments

Enable Address Fields in Magento Customer Registration Forms

Magento Logo

In order to enable address fields in Magento customer registration forms you only need to enable the attribute setShowAddressField.

To do so either add the following in your template or in the base local.xml (/app/design/frontend/base/default/layout/local.xml):

<customer_account_create> 
  <reference name="customer_form_register"> 
    <action method="setShowAddressFields">
      <param>true</param>
    </action> 
  </reference>
</customer_account_create>

As always, make sure to reload your cache afterwards. This setting will enable to execution of

<?php if($this->getShowAddressFields()): ?>

in register.phtml (/app/design/frontend/base/default/template/customer/form/register.phtml). That’s it 🙂

Posted on 1 Comment

Enabling Cross-Origin Resource Sharing CORS for Apache

Apache Logo

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.