cakephp with angularjs



CORS Cakephp 3.0 preflight for put/delete fails (0)

I'm trying to make CORS working within my application. But the preflight OPTIONS call for PUT and DELETE is failing all the time. For example the PUT request:

OPTIONS /api/events/5b165c71-0676-4d67-aceb-5546aff8ea03 HTTP/1.1
Host: rest.app
Connection: keep-alive
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, content-type
Origin: http://frontend.app
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
Accept: */*
Referer: http://frontend.app/events/5b165c71-0676-4d67-aceb-5546aff8ea03/edit
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,fr;q=0.2,it;q=0.2

and the response from my server (CakePHP 3.0)

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, content-type
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:http://frontend.app
Access-Control-Max-Age:86400
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8
Date:Tue, 26 May 2015 15:21:24 GMT
Keep-Alive:timeout=5, max=100
Server:Apache
Transfer-Encoding:chunked
X-DEBUGKIT-ID:75441af3-02b0-4945-a82c-5607287d4994
X-Powered-By:PHP/5.6.7

the error message is:

OPTIONS http://rest.app/api/events/5b165c71-0676-4d67-aceb-5546aff8ea03
XMLHttpRequest cannot load
http://rest.app/api/events/5b165c71-0676-4d67-aceb-5546aff8ea03.
    Invalid HTTP status code 404

So the actual request is not allowed. I've set the withCredentials flag true in Angular. I'm I still trying to fix a CORS issue or is the bug with cakephp? I've tried to set the headers with php and with the htaccess. Nothing worked except GET and POST.

EDIT:

headers

if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

  if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
    header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
  }

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
}

CakePHP routes.php

$routes->resources('Chapters');

EventController

public function edit($id = null)
{
    // $this->autoRender = false;
    $event = $this->Events->get($id, [
        'contain' => []
    ]);

    if ($this->request->is(['patch', 'post', 'put'])) {
        $event = $this->Events->patchEntity($event, $this->request->data);
        if ($this->Events->save($event)) {
            $message = 'The event has been saved.';
        } else {
            $message = 'The event could not be saved. Please, try again.';
        }
    }
    $this->set(array(
        'event' => $event,
        '_serialize' => array('message')
    ));
}

The client making the call with Restangular.

Restangular.one('events',event.id).put();

$http didn't work as well as a plain request

xhr request.

  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open('PUT','http://rest.app/api/events/'+event.id,true);
  xmlhttp.send();

$http

   return $http({
     url: 'http://rest.app/api/events/'+event.id,
     method: "PUT",
     data: event,
     dataType: 'json',
     withCredentials: true,
     headers: {
       'Content-Type': 'application/json; charset=utf-8'
     }
 });

EDIT 2:

I just found out that if I do this it works even if I still get an error:

header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  die;
}

Does this get me any further? I know thats not the solution.

EDIT 3:

I just made it work with these changes. I'm not sure if I'm hacking or if I solved CORS right?!

AngularJS:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

CAKEPHP webroot/index.php

// Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);
}




cakephp-3.0