null, JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' ]; /** * 并行请求 * * @param array $requests 请求的数据 * @param Core $parent Core实例(通常为Controller实例) * @return array */ public static function request(array $requests, Core $parent) { $config = $parent->getConfig(); $serviceConf = $config->get('params.service', null); $parallelConf = $config->get('params.parallel'); $preParams = array_filter([ '__appVersion' => !empty($parent->getContext()->getInput()->postGet('__appVersion')) ? $parent->getContext()->getInput()->postGet('__appVersion') : $parent->getContext()->getInput()->postGet('appVersion'), '__locale' => !empty($parent->getContext()->getInput()->postGet('__locale')) ? $parent->getContext()->getInput()->postGet('__locale') : $parent->getContext()->getInput()->postGet('locale'), '__platform' => !empty($parent->getContext()->getInput()->postGet('__platform')) ? $parent->getContext()->getInput()->postGet('__platform') : $parent->getContext()->getInput()->postGet('platform') ]); $list = $result = []; foreach ($requests as $name => $params) { if (isset($parallelConf[$name])) { //服务名 $list[$name]['service'] = $service = $parallelConf[$name]['service'] ?? null; $list[$name]['host'] = $parallelConf[$name]['host'] ?? $serviceConf[$service]['host']; $list[$name]['timeout'] = $parallelConf[$name]['timeout'] ?? $serviceConf[$service]['timeout'] ?? 1000; $list[$name]['api'] = $parallelConf[$name]['url']; //优先使用parallel配置,然后有参数有POST,无参用GET $list[$name]['method'] = $parallelConf[$name]['method'] ?? (empty($params) ? 'GET' : 'POST'); $list[$name]['params'] = array_merge($params, $preParams); //合并参数; //结果解析方法 $list[$name]['parser'] = ($parallelConf[$name]['parser'] ?? 'normal') . 'Parser'; //dns请求 $list[$name]['dns'] = $parent->getObject(Client::class)->goDnsLookup($list[$name]['host'], $list[$name]['timeout']); } } foreach ($list as $name => $item) { /** * @var Client $client */ //dns结果 if ($item['dns'] instanceof DNS) { $item['dns'] = $item['dns']; if (!$item['dns']) { $parent->getContext()->getLog()->error('DNS lookup for ' . $item['host'] . ' Failed'); $result[$name] = false; unset($list[$name]); continue; } } //http请求 if ($item['method'] == 'POST') { $list[$name]['http'] = $item['dns']->goPost($item['api'], $item['params'], $item['timeout']); } else { $list[$name]['http'] = $item['dns']->goGet($item['api'], $item['params'], $item['timeout']); } } foreach ($list as $name => $item) { $response = $item['http']; $request = ['host' => $item['host'], 'api' => $item['api'], 'method' => $item['method'], 'params' => $item['params']]; // http 失败 if (!isset($response['body']) || empty($response['body'])) { $parent->getContext()->getLog()->error('The response of body is not found with response: ' . json_encode($response) . ' Request: ' . json_encode($request)); $result[$name] = false; unset($list[$name]); continue; } //解析结果 $parser = $item['parser']; $result[$name] = $parser === 'noneParser' ? $response : self::$parser($request, $response, $parent); } return $result; } /** * 结果解析器(常规) * * @param array $request 请求信息 * @param array $response 响应数据 * @param Core $parent Core实例(通常为Controller实例) * @return mixed|null */ protected static function normalParser(array $request, array $response, Core $parent) { try { $body = json_decode($response['body'], true); if ($body === null) { $error = static::jsonLastErrorMsg(); throw new BusinessException('json decode failure: ' . $error . ' caused by ' . $response['body'] . ' Request: ' . json_encode($request)); } return static::parseResponse($request, $body); } catch (BusinessException $businessException) { $parent->getContext()->getLog()->error($businessException->getMessage()); return null; } } /** * 解析返回值 * * @param array $request 请求参数 * @param array $responseBody 响应正文 * @return mixed * @throws BusinessException */ private static function parseResponse(array $request, $responseBody) { if (isset($responseBody['status']) == false || array_key_exists('data', $responseBody) == false || isset($responseBody['message']) == false ) { throw new BusinessException('Response The result array is incomplete. response=' . json_encode($responseBody) . ' Request: ' . json_encode($request)); } if ($responseBody['status'] != 200) { throw new BusinessException('Response returns the result status is not equal to 200. response=' . json_encode($responseBody) . ' Request: ' . json_encode($request)); } return $responseBody['data']; } /** * 拿到json解析最后出现的错误信息 * * @return mixed|string */ private static function jsonLastErrorMsg() { $error = json_last_error(); return array_key_exists($error, static::$jsonErrors) ? static::$jsonErrors[$error] : "Unknown error ({$error})"; } }