美文网首页
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