Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Luracast Restler callback parameter for cross-domain AJAX

Tags:

rest

php

I'm using Restler to implement a simple REST API. Now if I need to consume that API via AJAX from another domain, I'm going to need to send a callback parameter along with my requests. Is there support for this in Restler (I have yet to find any real documentation)?

like image 421
Tommy Brunn Avatar asked Nov 14 '11 16:11

Tommy Brunn


2 Answers

For anyone coming to this page from googling, I submitted an issue at github, and got excellent support from the author. Turns out it's fairly trivial to implement, if you're familiar with how Restler is built.

From https://github.com/Luracast/Restler/issues/17

<?php
//jsonpformat.php
class JsonpFormat implements iFormat {

    const MIME = 'text/javascript';
    const EXTENSION = 'js';
    /*
     * JsonFormat is used internally
     * @var JsonFormat;
     */
    public $jsonFormat;
    public static $functionName = 'parseResponse';

    public function __construct() {
        $this->jsonFormat = new JsonFormat ();
        if (isset ( $_GET ['jsonp'] )) {
            self::$functionName = $_GET ['jsonp'];
        }
    }
    public function getMIMEMap() {
        return array (self::EXTENSION => self::MIME );
    }
    public function getMIME() {
        return self::MIME;
    }
    public function getExtension() {
        return self::EXTENSION;
    }
    public function encode($data, $human_readable = FALSE) {
        return self::$functionName . '(' . $this->jsonFormat->encode ( $data, $human_readable ) . ');';
    }
    public function decode($data) {
        return $this->jsonFormat->decode ( $data );
    }
    public function setMIME($mime) {
        //do nothing
    }
    public function setExtension($extension) {
        //do nothing
    }
}
?>

This should be saved in the same directory as the restler.php file. Once you have that, edit your gateway (index.php) to include this file and add it as a supported format. Example:

<?php
require_once '../../restler/restler.php';

#set autoloader
#do not use spl_autoload_register with out parameter
#it will disable the autoloading of formats
spl_autoload_register('spl_autoload');

$r = new Restler();
$r->setSupportedFormats('JsonpFormat','JsonFormat', 'XmlFormat');
$r->addAPIClass('BMI');
$r->handle();
?>
like image 147
Tommy Brunn Avatar answered Oct 02 '22 20:10

Tommy Brunn


This worked well for us: header('Access-Control-Allow-Origin: *');

Add this to a controller method prior to the return for a single end point, to the controller class constructor for all endpoints in that branch or higher up to allow it site wide.

If you are only allowing certain sites to access use header('Access-Control-Allow-Origin: example.com') or something like header('Access-Control-Allow-Origin: '. $remote_domain). Where $remote_domain is set dynamically based on some passed in token or such. Check out Cross-Origin Resource Sharing (CORS) for why to limit the use of * wildcard.

<?php

class Say {

__construct(){
  header('Access-Control-Allow-Origin: *'); //Here for all /say
}

function hello($to='world') {
   header('Access-Control-Allow-Origin: *'); //Here for just /say/hello 
   return "Hello $to!";
  }
}

The above works for GET and POST, other actions require some additional header info from restler. Here are some examples:

header('Access-Control-Allow-Methods: GET, POST, DELETE, PUT, OPTIONS'); header('Access-Control-Allow-Headers: whatever_headers_you_allow, header1, header2');

For IE9 and below you will need to a JSONP hack. Restler has example of extending the iFormat class to wrap the API output JASONP style.

Check out Mozilla hacks for details on CORS. http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ And check out OPTIONS in PHP REST API

like image 43
punkael Avatar answered Oct 02 '22 20:10

punkael