Ошибки в waNet Принято

2

1. При получении сжатых данных ('Content-Encoding: gzip') результат не распаковывается перед декодированием в json/xml и возникает ошибка.

2. Результат предыдущего запроса обнуляется не вначале следующего запроса, а под конец, поэтому в случае ошибки в необработанном ответе может оказывается результат предыдущего запроса.

3. Результат запроса декодируется до проверки кода по 'expected_http_code', соответственно  вместо исключения о неверном результате запроса получаем исключение о неверном формате данных (выполняется бесполезное декодирование).

4. Не логируются ошибки при декодировании json.

Вот как примерно должно быть:

public function query($url, $content = array(), $method = self::METHOD_GET, $callback = null)
{
    // Reset response
    $this->decoded_response = null;
    $this->raw_response = null;
    $this->response_header = array('http_code' => 500);
    
    $this->buildRequest($url, $content, $method);
    $this->startQuery();
    
    switch ($this->getTransport($url)) {
        case self::TRANSPORT_CURL:
            $this->raw_response = $this->runCurl($url, $content, $method, array(), $callback);
            break;
        case self::TRANSPORT_FOPEN:
            $this->raw_response = $this->runStreamContext($url, $content, $method);
            break;
        case self::TRANSPORT_SOCKET:
            $this->raw_response = $this->runSocketContext($url, $content, $method);
            break;
        default:
            throw new waException('There no suitable network transports', 500);
    }
    
    if ($this->raw_response instanceof self) {
        return $this->raw_response;
    }
    $this->onQueryComplete($this->raw_response);
    return $this->getResponse();
}

protected function onQueryComplete($response)
{
    // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
    $encoding = $this->getResponseHeader('Content-Encoding');
    if (in_array($encoding, array('gzip', 'x-gzip')) && function_exists('gzinflate')) {
        // @see http://php.net/manual/ru/function.gzinflate.php#100775
        $response = gzinflate(substr($response, 10, -8));
    }
    
    if ($this->options['expected_http_code'] !== null) {
        if (!is_array($this->options['expected_http_code'])) {
            $this->options['expected_http_code'] = preg_split('@[,:;.\s]+@', $this->options['expected_http_code']);
        }
        $code = $this->getResponseHeader('http_code');
        if (!in_array($code, $this->options['expected_http_code'])) {
            throw new waException($response, $code ? $code : 500);
        }
    }
    
    $this->decodeResponse($response);
}

protected function decodeResponse($response)
{
    switch ($this->options['format']) {
        case self::FORMAT_JSON:
            try {
                $this->decoded_response = waUtils::jsonDecode($response, true);
            } catch (waException $e) {
                $this->log($e->getMessage());
                throw new waException('Error while decode JSON response: '.$e->getMessage(), $e->getCode());
            }
            break;
        case self::FORMAT_XML:
            libxml_clear_errors();
            libxml_use_internal_errors(true);
            libxml_disable_entity_loader(false);
            $xml_options = LIBXML_NOCDATA | LIBXML_NOENT | LIBXML_NONET;
            $this->decoded_response = @simplexml_load_string($response, null, $xml_options);
            if ($this->decoded_response === false) {
                /**
                 * @var LibXMLError $error
                 */
                if ($error = libxml_get_last_error()) {
                    $this->log($error->message);
                    throw new waException('Error while decode XML response: '.$error->message, $error->code);
                }
            }
            break;
        default:
            $this->decoded_response = $response;
    }
}

2 комментария

  • +1
    Syrnik.com Syrnik.com 27 февраля 2019 13:11 #

    3 пункт спорный

    многие api возвращают ошибку, например авторизации, с сооветствующим кодом и объект ошибки в теле ответа.

    Ну, можно, конечно, поймав исключение, декодировать самостоятельно. Но зачем?

    • +1
      enso_studio@mail.ru enso_studio@mail.ru 27 февраля 2019 14:04 #

      В большинстве случаев ошибки 4хх имеют формат строки или вообще не имеет тела и при попытке их декодировать возникает ошибка. Предложенный вариант таких проблем не имеет, если требуется декодировать ответ для 5хх ошибок которые действительно идут чаще всего в том же формате, то их нужно указать в 'expected_http_code'.

      Добавить комментарий

      Чтобы добавить комментарий, зарегистрируйтесь или войдите