在 Skiddle 上提出 API 请求时出现问题:301 已移动

问题描述 投票:0回答:2

我正在尝试通过 skiddle API 请求事件,使用端点http://www.skiddle.com/api/v1/events/search/,但是当我尝试时,我得到以下响应:

HTTP/1.1 301 Moved Permanently
Server: CloudFront
Date: Wed, 19 Apr 2023 14:21:19 GMT
Content-Type: text/html
Content-Length: 167
Connection: keep-alive
Location: https://www.skiddle.com/api/v1/events/search/?api_key=adda7f84a6e81df4c571792014aa321a&latitude=51.509865&longitude=-0.118092&radius=30&keyword=trance&limit=100&offset=0
X-Cache: Redirect from cloudfront
Via: 1.1 3fff5cbe8229c22a8e7cfe60a8827a1e.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: LHR61-P6
Alt-Svc: h3=":443"; ma=86400
X-Amz-Cf-Id: SLXpElnGSXFF0oD360hjXiwDF2sqfuHD5LggX96rDlUaoHGecskp1Q==

这是我的代码:

$skiddle = new Skiddle();
$rr = $skiddle->searchEvents('london','trance');
echo $rr->get();

class Locations
{
    public static $london = [
        'latitude'=>51.509865,
        'longitude'=>-0.118092,
        'radius'=>30
    ];
}
class Skiddle
{
    const EVENTS_SEARCH_URL = 'http://www.skiddle.com/api/v1/events/search/';
    const KEY = "adda7f84a6e81df4c571792014aa321a";
    public function __construct(){}
    public function searchEvents($location = "", $keyword = "")
    {
        $params = [
            'api_key' => self::KEY
        ];
        if ($location)
        {
            $params['latitude'] = Locations::$$location['latitude'];
            $params['longitude'] = Locations::$$location['longitude'];
            $params['radius'] = Locations::$$location['radius'];
        }
        if ($keyword)
        {
            $params['keyword'] = $keyword;
        }
        return new SkiddlePaginatedRequestResponse(
            self::EVENTS_SEARCH_URL,
            $params
        );
    }
}
class SkiddlePaginatedRequestResponse extends RequestResponse
{
    protected $limit;
    protected $offset;
    public function __construct($url, $params = [], $limit = 100, $offset = 0)
    {
        parent::__construct($url, $params);
        $this->limit = $limit;
        $this->offset = $offset;
    }
    public function get()
    {
        return parent::get();
    }
    public function nextPage()
    {
        return new SkiddlePaginatedRequestResponse(
            $this->url,
            $this->params,
            $this->limit,
            $this->offset + $this->limit
        );
    }
    protected function buildRequest()
    {
        parent::buildRequest();
        $this->request['limit'] = $this->limit;
        $this->request['offset'] = $this->offset;
    }
    protected function handleBadStatus($rawBody, $status, $headers)
    {
        $errorBody = json_decode($rawBody);
        if (isset($errorBody->errormessage) && isset($errorBody->error)) {
            // Error from the API
            fault("Skiddle error", $errorBody->errormessage."\n".$errorBody->error);
            die();
        } else {
            $this->dieHttpErrorFault($status, $headers);
        }
    }
}
class RequestResponse
{
    protected $params;
    protected $url;
    protected $request;
    protected $cookies = false;
    public function __construct($url, $params = [])
    {
        $this->params = $params;
        $this->url = $url;
    }
    public function setCookies($cookies)
    {
        //"mycookie1=value1; mycookie2=value2"
        $this->cookies = $cookies;
    }
    public function get()
    {
        $this->buildRequest();
        $url = $this->url . '?' . http_build_query($this->request);
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_HEADER => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_URL => $url,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        if ($this->cookies) curl_setopt($ch, CURLOPT_COOKIE, $this->cookies);
        $response = curl_exec($ch);
        //$rawBody = curl_exec($ch);
        if (curl_error($ch))
        {
            fault('cURL transport error', curl_errno($ch).'\n'.curl_error($ch));
            die();
        }
        list($headers, $rawBody) = explode("\r\n\r\n", $response, 2);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($status < 200 || $status > 299) {
            $this->handleBadStatus($rawBody, $status, $headers);
        }
        $object = json_decode($rawBody, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            fault('JSON parsing', "Error ".json_last_error_string()." (".json_last_error().")");
        }
        return $object;
    }
    protected function buildRequest()
    {
        $this->request = $this->params;
    }
    protected function handleBadStatus($rawBody, $status, $headers)
    {
        $this->dieHttpErrorFault($status, $headers);
    }
    protected function dieHttpErrorFault($status, $headers)
    {
        fault('HTTP error', "Code $status, \nHeaders:\n$headers");
        die();
    }
}

请指教 谢谢

php api http-status-code-301 skiddle-api
2个回答
1
投票

301 表示已移动资源(或重定向,如果您愿意)。可能有几个原因,但我的猜测是他们将您的

http
请求重定向到
https
所以解决方案只是将 URL 更正为使用
https
。或者,您可以按照其他人的建议设置
CURLOPT_FOLLOWLOCATION
,但这不是最佳选择,因为即使您现在知道第一个是静脉+您的第一个未加密,您也会执行两个请求。

编辑: 我还注意到您的

searchEvents()
实现中存在错误。这些行:

$params['latitude'] = Locations::$$location['latitude'];
$params['longitude'] = Locations::$$location['longitude'];
$params['radius'] = Locations::$$location['radius'];

对我来说很臭,因为你正在使用可变变量 (

$$
)。我怀疑复制粘贴错误,所以我建议开始使用任何静态 linter 或至少更智能的 IDE :)


0
投票

一般来说,使用

CURLOPT_FOLLOWLOCATION
https://www.php.net/manual/en/function.curl-setopt.php)选项让cURL自动跟随重定向。

在您的特定情况下,它似乎只是

http://
https://
协议重定向,您可以通过直接向
https://
版本发出请求来简单地克服它。这将避免一直发出 2 个请求。

© www.soinside.com 2019 - 2024. All rights reserved.