CORS Example with PHP

Mostly serving web pages you have the capability to do dynamic scripting since it is done on the same server. However if you do need to do this CORS allows the mechanism. Explained well at this link: http://enable-cors.org/

“JavaScript and the web programming has grown by leaps and bounds over the years, but the same-origin policy still remains. This prevents JavaScript from making requests across domain boundaries, and has spawned various hacks for making cross-domain requests.

CORS introduces a standard mechanism that can be used by all browsers for implementing cross-domain requests. The spec defines a set of headers that allow the browser and server to communicate about which requests are (and are not) allowed. CORS continues the spirit of the open web by bringing API access to all.”

In my case I wanted to proof this because I have a http enabled S3 bucket on Amazon AWS. Meaning all static. So one example of a need for this would be a contact form or quick lookup in a database etc. My example below is very simple. S3 website has a submit form button that use javascript to send the request to a PHP enable nginx server. PHP script look up the JSON value passed to it in an array and pass the value back.

S3 static web page:

<html>

<head>
<script type="text/javascript">

//window.onload = doAjax();

function doAjax(last_name) {
    var url         = "http://my.phpserver.domain/api/cors_contact.php";
    
    //var request     = JSON.stringify({searchterm:"doe"});
    //var search_st  = 'searchterm:' + 'last_name';
    //alert(search_st);
    var request     = JSON.stringify({searchterm:last_name});
    //alert (request);
    var xmlhttp     = new XMLHttpRequest();

    xmlhttp.open("POST", url);
    xmlhttp.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
    xmlhttp.setRequestHeader("Access-Control-Allow-Origin", "*");
    xmlhttp.setRequestHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    xmlhttp.setRequestHeader("Access-Control-Allow-Headers", "Content-Type");
    xmlhttp.setRequestHeader("Access-Control-Request-Headers", "X-Requested-With, accept, content-type");

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var jsondata = JSON.parse(xmlhttp.responseText);
            //document.getElementById("id01").innerHTML = xmlhttp.responseText;
            document.getElementById("id02").innerHTML = jsondata.word;
        }
    };

    xmlhttp.send(request);
}

function searchKeyPress(e)
{
    // look for window.event in case event isn't passed in
    e = e || window.event;
    if (e.keyCode == 13)
    {
        document.getElementById('Submit').click();
        return false;
    }
    return true;
}

</script>
</head>
<body>
<div id="id01"></div>
<div id="id02"></div>
<form name="contactform" id="controlsToInvoke" action="">
<table width="450px">
<tr>
<td valign="top"">
  <label for="last_name">Last Name *</label>
 </td>
<td valign="top">
  <input type="text" id="last_name" name="last_name" maxlength="50" size="30" onkeypress="return searchKeyPress(event);" />
 </td>
</tr>
<tr>
<td colspan="2" style="text-align:center">
  <input type="button" id="Submit" value="Submit" onclick="doAjax(document.getElementById('last_name').value)" />
 </td>
</tr>
</table>
</form>
</body>
</html>

PHP script.

In this case you can see all the headers are handled inside the PHP script. You can of course handle it with the web server also. Details for web servers here: http://enable-cors.org/server.html

<?php $dictionary = array('doe' => 'j.doe@email.domain', 'smith' => 'asmith@email2.domain', 'stranger' => 'noname@noname.com');

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');
    }
    exit;
}

$json = file_get_contents('php://input');
$obj = json_decode($json);

if (array_key_exists($obj->searchterm, $dictionary)) {
    $response = json_encode(array('result' => 1, 'word' => $dictionary[$obj->searchterm]));
}
else {
    $response = json_encode(array('result' => 0, 'word' => 'Not Found'));
}

header('Content-type: application/json');
header('Access-Control-Allow-Origin: *');
echo $response;

Thanks to this excellent reference. There are a lot of very confusing discussions on this topic. Especially around pre-flight checking.
http://www.mjhall.org/php-cross-origin-resource-sharing/

Creating a javascript array with one to many type relationship

Sometimes I need to build an array of lists with a one to many type relationship.

For example this data:
1. item1 has a parent of key1.
2. item2 has a parent of key2.
3. item3 has a parent of key1.

Using PHP after packing the array I will end up with something like this:

<?php

$m = array();

$m['key1'][] = 'item1';
$m['key2'][] = 'item2';
$m['key1'][] = 'item3';

print_r($m);

?>

Result:

Array
(
    [key1] => Array
        (
            [0] => item1
            [1] => item3
        )

    [key2] => Array
        (
            [0] => item2
        )

)

In javascript there is some options to do something similar. I ended up with something like this:
packedArr[‘key1’] = “item1,item3”
packedArr[‘key2’] = “item2”

Not exactly array in array[key] but the comma separated list did what I needed.

Here is the javascript itself. To test it you can use online javascript testers or just make up a html page with a button and maybe have onclick display document.getElementById(“demo”).innerHTML = output;

<script>
function packArr() {
var pA = Array();

var inA = [ 
  ["child1","parent1"],
  ["child2","parent2"],
  ["child3","parent1"],
  ["child4","parent1"],
  ["child5","parent2"]
  ];

var inALen = inA.length;
for (var i = 0; i < inALen; i++) {
    //alert(inA[i]);
  if (pA[inA[i][1]] == null) {
     pA[inA[i][1]] = inA[i][0];
  } else {
    pA[inA[i][1]] = pA[inA[i][1]] + "," + inA[i][0];
  }
}

res="";
for ( var key in pA ) { 
  res = res + key + ": " + pA[key] + "<br>";
};
//res = myArray["parent1"]; 
document.getElementById("demo").innerHTML = res;
}
</script>