PHP cURL - Link Header

PHP cURL - Link Header

我制作了一个与 GitHubs API 交互的代码搜索应用程序,我想向其中添加分页,分页数据保存在 header 中,如下所示:

Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next", <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"

我的代码:

    // API CONNECTION
    $url = 'https://api.github.com/search/code?q=' . $term  . '+language:' . $lang . '&per_page=' . $pp;
    $cInit = curl_init();
    curl_setopt($cInit, CURLOPT_URL, $url);
    curl_setopt($cInit, CURLOPT_RETURNTRANSFER, 1); // 1 = TRUE
    curl_setopt($cInit, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
    curl_setopt($cInit, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($cInit, CURLOPT_USERPWD, $user . ':' . $pwd);
    curl_setopt($cInit, CURLOPT_HTTPHEADER, array('Accept: application/vnd.github.v3.text-match+json')); // ADD THE HIGHLIGHTED CODE SECTION

    // MAKE CURL OUTPUT READABLE
    $output = curl_exec($cInit);
    $items = json_decode($output, true); 
    curl_close($cInit); // CLOSE OUR API CONNECTION

现在,我添加了 curl_setopt($cInit, CURLOPT_HEADER, true);

现在,无论出于何种原因 - 当我在将 CURLOPT_HEADER 添加到我的代码之前执行 var_dump($items) 时 - 而不是 returns 和 NULL。这反过来又破坏了整个项目。

做一些调试我发现 var_dump($output) 仍在输出数据,并且正如预期的那样包含了 header。但是,Link Header 看起来像这样:

Link: ; rel="next", ; rel="last" 在不应该的时候。据我所知,link header 似乎已经破坏了我的代码。

我尝试了各种方法,比如在解码之前尝试 urlencode $output,但无济于事。那么,我该如何解决这个问题?

However, the Link Header looks like this:

Link: ; rel="next", ; rel="last"

听起来您正在使用浏览器查看输出,它只是将 <> 之间的 link URL 解释为文本。

使用 var_dump 而不是 echo 进行调试。或者,简单地使用浏览器的源代码视图。

设置 curl_setopt($cInit, CURLOPT_HEADER, true);(或 1 而不是 true)意味着 $output 变量还 includes the headers。这就是为什么尝试 json_decode() 它不起作用 - header 位于顶部,它不再是有效的 JSON 字符串。

This SO question has more details on the various ways you can try and parse out the headers from your body, depending on the needs of your server. If you're not using proxies, redirects or anything odd, then the accepted answer 来自那个问题可能对你有用(适应你的变量):

$header_size = curl_getinfo($cInit, CURLINFO_HEADER_SIZE);
$header = substr($output, 0, $header_size);
$body = substr($output, $header_size);

如果您担心,因为您正在与 Github 打交道,并且您不了解他们的基础设施或他们可能会对您做出什么改变 (Github search documentation does warn it may change without advance notice after all), then you may be better off using the CURLOPT_HEADERFUNCTION option, which lets you assign a callback function to parse each (every) header that comes back from the cURL request. What the value of this must be (from the documentation):

A callback accepting two parameters. The first is the cURL resource, the second is a string with the header data to be written. The header data must be written by this callback. Return the number of bytes written.

您可以在之前的同一个 SO 问题中看到这方面的示例 - 它可以是常见的微不足道的情况 (a named function, or a PHP callable array), or even a closure which populates a global $headers array.

测试了这些方法后,Link header 对我正确显示 如果 有超过一页的结果。如果只有一页(或没有结果),则 Link header 将从 Github 响应中完全省略。

在不知道您对 $term$lang$pp 使用什么的情况下,这可能有点棘手。由于您还使用 $user$pw 组合进行授权,因此使用常规 API 端点用于 publicly 消费数据可能会有所不同。我会使用搜索查询进行检查,您 知道 首先在 public 存储库中有很多页的结果。

最后但并非最不重要的一点是,如果您正在编写一个应用程序来使用 Github API,我建议您站在前人的肩膀上。例如,KNP 实验室有一个 Github API wrapper for PHP which is very popular (with documentation on search and pagination), or if you're using Laravel there's a wrapper by Graham Campbell.

我在 Shopify 中遇到了同样的分页问题 API; headers 一直工作到 Link 元素,它只返回 6 个字符的字符串 (<https)。这两行代码对我有用(请注意,我在第二行中使用了 htmlspecialchars() 以便我可以在浏览器中使用 var_dump($header);

查看它
$header_size = curl_getinfo($cInit, CURLINFO_HEADER_SIZE);
$header = htmlspecialchars(substr($output, 0, $header_size));