今天又一次捡起了老 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 下载
其中有一个接口是下载表格文件的,直接用上面的接口必然出错。于是新建了接口干了两件事:
- 将 JSON 解析的行为去掉
- 在返回响应的时候将 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()
来调用接口的。 - 继续对技术、语言、框架保持开放的态度,做一个全栈工程师。
网友评论