刘贵学博客

Thinkphp 中 json RPC 的跨域方案

1. 跨域支持

Web server 的配置(nginx)

   location ~ \.php$ {

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers Origin,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,X-Requested-With,Content-Type,Accept;
    add_header Access-Control-Allow-Methods POST;

    fastcgi_intercept_errors on; 
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  fastcgi_script_name;
    include /usr/local/etc/nginx/fastcgi.conf;
}

Thinkphp中的配置 ThinkPHP/Library/Vendor/jsonRPC/jsonRPCServer.php

if( $_SERVER['Access-Control-Request-Method'] != 'POST' &&   // support nginx cross-domain.
    $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] != 'POST') // support apache CORS cross-domain.
    {

        if (
            $_SERVER['REQUEST_METHOD'] != 'POST' || 
            empty($_SERVER['CONTENT_TYPE']) ||
                (   $_SERVER['CONTENT_TYPE'] != 'application/json' &&
                    $_SERVER['CONTENT_TYPE'] != 'application/json; charset=UTF-8'
                )
            ) 
        {
            // This is not a JSON-RPC request
            $dbg = json_encode($_SERVER);
            Log::err("Not a json rpc client_SERVER=$dbg");
            return false;
        }

    }

2 用 PHP 作为代理实现跨域

以上配置 nginx的 CORS,但是对 IE8以下的浏览器兼容不好,可以直接使用一个简单的php脚步作为代理
在调用者的根目录新建 API.php。

<?php 

function curl_post($url, $post_data, $timeout=3)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);


$headers = array("Content-type: application/json; charset=UTF-8",
                "Accept: application/json",
                "Cache-Control: no-cache",
                "Pragma: no-cache");

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$output = curl_exec($ch);

curl_close($ch);

return $output;
}



$host = "http://remote_server/API.php?c=".$_GET['c'];
$req = file_get_contents('php://input');

$out = curl_post($host, $req);

echo($out);

 ?>

TODO:

Thinkphp 只支持 JSON-RPC 1.0 规格,不支持 批量操作。
* http://www.kancloud.cn/thinkphp/json-rpc-2/43544