美文网首页
PHP 利用 curl 转发接口遇到的问题

PHP 利用 curl 转发接口遇到的问题

作者: VioletJack | 来源:发表于2023-02-09 08:11 被阅读0次

    今天又一次捡起了老 PHP 项目来维护,遇到需要转发 Java 项目后端接口的需求。

    接口转发

       private function _req_data ($path, $params = null) {
          $url =  $this->rootUrl . $path;
          if ($params) {
              $first = true;
              foreach ($params as $k => $v) {
                  if ($first) {
                      $url .= '?';
                      $first = false;
                  } else {
                      $url .= '&';
                  }
    
                  $url .= "$k=$v";
              }
          }
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, $url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch, CURLOPT_TIMEOUT,60);
          $output = json_decode(curl_exec($ch), true);
          curl_close($ch);
    
          if (!isset($output['code'])) {
              throw  new Exception("no code in datasvc resp");
          }
    
          if ($output['code'] != 200) {
              throw  new Exception("bad code in datasvc resp " . $output['code'] . " " . $output['message']);
          }
    
          return $output['data'];
        }
    

    CSV 下载

    其中有一个接口是下载表格文件的,直接用上面的接口必然出错。于是新建了接口干了两件事:

    1. 将 JSON 解析的行为去掉
    2. 在返回响应的时候将 Content-Type 文件类型头改掉。
        private function _req_data_csv ($path, $params = null) {
          $url =  $this->rootUrl . $path;
          if ($params) {
              $first = true;
              foreach ($params as $k => $v) {
                  if ($first) {
                      $url .= '?';
                      $first = false;
                  } else {
                      $url .= '&';
                  }
    
                  $url .= "$k=$v";
              }
          }
    
          header('Content-Type: text/csv');
          header('Content-Disposition: attachment; filename=download.csv');
    
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, $url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch, CURLOPT_TIMEOUT,60);
          $output = curl_exec($ch);
          $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);
    
          if (!($httpcode >= 200 && $httpcode < 400)) {
            Log::error("proxy_dsc error get " . $baseurl . " " . $httpcode . " " . $raw_output);
            return response(['msg' => '内部错误'], 500);
          }
    
          return $output;
        }
    

    中文字符转发异常

    由于我们是 vue前端 => PHP后端 => Java后端 这个流程,所以我在 Vue 传过去的中文字符,到了 Java 这里变成了一串十六进制字符,解决方法是在 PHP 层转发的时候调用 urlencode() 函数

    统一封装和使用

    在 controller 中进行封装和使用。

     private function getCsData(Request $request, $path, $isCsv = false) {
          $reqCtx = $request->all();
    
          $params = [
              "game_id" => $reqCtx['game_id'],
              "date1" => $reqCtx['date1'],
              "date2" => $reqCtx['date2'],
          ];
    
          if (isset($reqCtx['add_or_reduce'])) {
              $params['add_or_reduce']  = urlencode($reqCtx['add_or_reduce']);
          }
          if (isset($reqCtx['money_types'])) {
              $params['money_types']  = urlencode($reqCtx['money_types']);
          }
          if (isset($reqCtx['vdesc'])) {
            $params['vdesc']  = urlencode($reqCtx['vdesc']); 
          }
          if (isset($reqCtx['zone_ids'])) {
              $params['zone_ids']  = urlencode($reqCtx['zone_ids']);
          }
    
          if ($isCsv) {
            return $this->_req_data_csv($path, $params);
          }
          return ['data' => $this->_req_data($path, $params)];
        }
    
        public function getCsTable(Request $request) {
          return $this->getCsData($request, '/api/v1/web/game/cs-live/table');
        }
    
        public function getCsTableCsv(Request $request) {
          return $this->getCsData($request, '/api/v1/web/game/cs-live/table/csv', true);
        }
    
    

    思考

    接口的转发其实就是进行了两次接口请求和响应的过程,所以在 PHP 层使用 curl 来发起的请求。

    • 在前端,接口请求使用 fetch、XHR,在后端使用 curl
    • 网络基础知识很重要,否则很多网络相关问题都不知道如何找问题。
    • 另外,我也发现在 node 中也是使用了 this.ctx.curl() 来调用接口的。
    • 继续对技术、语言、框架保持开放的态度,做一个全栈工程师。

    参考资料

    相关文章

      网友评论

          本文标题:PHP 利用 curl 转发接口遇到的问题

          本文链接:https://www.haomeiwen.com/subject/rygqkdtx.html