簡易NodeJS、PHP跨域代理[Restful請求]打賞

最近測試一些東西,需要跨域訪問Restful接口,因為是測試,不可能改變接口形式,所以jsonp方案直接Pass。

本地測試時簡單寫了幾行NodeJS代碼,對特定路徑下的請求進行轉發后回傳,因為使用WebStorm開發,NodeJS不可以和WebStorm內置服務器使用相同端口,雖然可以通過配置本地服務器,完全將NodeJS作為服務器,但那樣需要解決靜態資源的輸出,寫東西過多,偏離初衷,這里不再贅述。

不過如果你是做前后端完全分離的項目,大可以找個開源的Web框架來用,比如express等,這里不多介紹。

總之但思路就這樣了,可能不太完善,代碼如下:

/**
 * Created by William.Wei on 2016/4/23.
 */
var http = require('http');

var server = http.createServer();

server.on('request', function (request, response) {
    console.log(request.url);
    response.setHeader('Access-Control-Allow-Origin','*');
    response.setHeader('Content-type', 'text/html;charset=UTF-8');
    http.request({
        hostname: 'www.pswuul.tw',
        port: 80,
        path: request.url,
        method: request.method
    }, function (res) {
        res.on('data', function (data) {
            response.write(data);
        });
        res.on('end', function () {
            response.end();
        });
    }).end();
});

server.listen(88);

如上,因為是不同端口,所以本質上采用的CORS,所以僅僅是中轉思路而已,通過Web端ajax入口url統一處理后訪問端口為88的地址即可。

本地沒問題了,想放到外網玩呢?如果有托管主機或者VPS啥的還好,個人是不喜歡折騰,平時測些簡單的頁面啥的,直接丟虛擬主機,因為目前可以跑NodeJS的虛擬主機寥寥無幾,就想到了PHP,剛好公司有人封裝有Restful請求工具,參考源代碼簡化處理了一下,最終代碼如下:

<?php
class Rest
{

    private $baseURL;
    private $http_headers = [];
    private $curl_opts;
    private $method;
    private $params = [];
    private $urlParam = "";
    private $httpHeader = [];
    private $acceptXmlType = "Accept:application/xml";
    private $acceptJsonType = "Accept:application/json";

    public function __construct($method, $baseURL = '')
    {
        $this->baseURL = $baseURL;
        $this->method = $method;
        $this->curl_opts = array(
            CURLOPT_CONNECTTIMEOUT => 60,   /* 在發起連接前等待的時間,如果設置0,則無限等待 */
            CURLOPT_TIMEOUT => 300,  /* 允許執行的最長秒 */
            CURLOPT_USERAGENT => 'poorren.com',
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_FOLLOWLOCATION => false,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false
        );
    }


    private function getUrlParams()
    {
        return $this->urlParam;
    }

    private function getSetting()
    {
        if ($this->method == "POST") {
            // post數據
            $this->curl_opts[CURLOPT_POST] = true;
            if (is_string($this->params)) {
                $this->curl_opts[CURLOPT_POSTFIELDS] = $this->params;
            } else {
                $this->curl_opts[CURLOPT_POSTFIELDS] = json_encode($this->params, JSON_UNESCAPED_UNICODE);
            }
        } else if ($this->method == "PUT") {
            // put數據
            $fields = is_array($this->params) ? http_build_query($this->params) : $this->params;
            $this->curl_opts[CURLOPT_CUSTOMREQUEST] = 'PUT';
            $this->curl_opts[CURLOPT_RETURNTRANSFER] = true;
            $this->curl_opts[CURLOPT_POSTFIELDS] = $fields;
        } else {
            $urlParam = "";
            if ($this->params != null) {
                foreach ($this->params as $key => $value) {
                    $urlParam = $urlParam . "$key=" . urlencode($value) . "&";
                }
            }
            $this->urlParam = $urlParam;
        }

        $this->curl_opts[CURLOPT_HTTPHEADER] = $this->httpHeader;

        return $this->curl_opts;
    }

    private function execute($resource)
    {
        $ch = curl_init();
        curl_setopt_array($ch, $this->getSetting());
        if (!empty($this->http_headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $this->http_headers);
        }
        $urlParams = $this->getUrlParams();
        if (strpos($this->baseURL . $resource, '?') > 0) {
            $requestUrl = $this->baseURL . $resource . "&" . $urlParams;
        } else {
            $requestUrl = $this->baseURL . $resource . "?" . $urlParams;
        }

        curl_setopt($ch, CURLOPT_URL, $requestUrl);

        $result = curl_exec($ch);
        $code = curl_errno($ch);
        if ($code != 0) {
            $msg = curl_error($ch) . " request url is ({$code}):" . $requestUrl;
            throw new Exception($msg, $code);
        }

        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($http_code != 200) {
            throw new Exception($requestUrl);
        }

        return $result;
    }

    public function invoke($path, $params, $jsonParse = true, $acceptType = 'json')
    {
        $this->params = $params;
        if ($acceptType == 'xml') {
            $this->httpHeader[0] = $this->acceptXmlType;
        } else {
            $this->httpHeader[0] = $this->acceptJsonType;
        }
        $content = $this->execute($path);
        return $jsonParse ? json_decode($content) : $content;
    }

    public function setHeaders($headers)
    {
        if (empty($headers)) {
            return;
        }

        foreach ($headers as $k => $v) {
            $this->http_headers[$k] = $v;
        }
    }
}

仔細看的同學可能發現了,這個貌似和上次發的圖片代理《兩行代碼繞過基于referrer的防盜鏈》有類似作用,感興趣的同學可以以此為基礎來改造一下,就是個全功能圖片代理。

以上為開發、測試用代碼,僅分享,不建議使用到生產環境。

簡易NodeJS、PHP跨域代理[Restful請求]
文章《簡易NodeJS、PHP跨域代理[Restful請求]》二維碼
  • 微信打賞
  • 支付寶打賞

已有2條評論

  1. 夜盡迗明

    2016-09-22 18:03 回復
  2. 劉明野博客

    寫的很好,感謝分享

    2016-09-03 20:02 回復

(必填)

(必填)

(可選)

黑龙江22选5开奖