首页 > 解决方案 > 在 PHP 中使用 cURL 时如何避免重定向

问题描述

我想从 PHP 调用我的 Google App Script Web 服务,并且我正在尝试使用 cURL,并使用 GET 方法作为初学者。该服务以简单的文本yes进行响应。我找到了执行 GET 请求的 PHP 函数(见下文)。

来自 App Script 服务的第一个响应始终是重定向,因此我在获取函数的配置数组中关闭了以下重定向,读取了 url 并执行了另一个请求。但是,在第二个请求 url 上,我被重定向到服务 url(文本作为服务的结果显示),这是不可取的。我想以编程方式处理响应,而不是让 cURL 影响浏览器中的输出或行为。

初始状态及其工作方式:

  1. 我有一个正常运行的 App Script Web 服务 URL。
  2. Web 服务返回文本yes
  3. 我有一个调用 Web 服务的 PHP 脚本。
  4. 调用后,PHP 脚本会回显服务返回的内容。
  5. 在显示服务返回的内容后,PHP 脚本会回显单词hello

在浏览器中打开 PHP 脚本时实际发生的情况:

  1. 我执行第一个 GET 请求并获得响应。
  2. 我从响应中获取redirect_url并对其执行第二个 GET 请求。
  3. 单词hello会在其上显示一秒钟,但仍会显示 PHP 脚本的 url。
  4. 浏览器中的 URL 更改为服务的 URL,hello消失,服务响应yes出现(可能刚刚被重定向)。

我使用的 PHP 脚本:

$response = get_web_page($url);

$url2 = $response["redirect_url"];

$response = get_web_page($url2);

echo $response["content"];

echo "hello";

我用来获取 URL 的 PHP 函数:

function get_web_page( $url, $cookiesIn = '' ){
        $options = array(
            CURLOPT_RETURNTRANSFER => true,     // return web page
            CURLOPT_HEADER         => true,     //return headers in addition to content
            CURLOPT_FOLLOWLOCATION => false,     // follow redirects
            CURLOPT_ENCODING       => "",       // handle all encodings
            CURLOPT_AUTOREFERER    => false,     // set referer on redirect
            CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
            CURLOPT_TIMEOUT        => 120,      // timeout on response
            CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects
            CURLINFO_HEADER_OUT    => true,
            CURLOPT_SSL_VERIFYPEER => true,     // Validate SSL Cert
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
            CURLOPT_COOKIE         => $cookiesIn
        );

        $ch      = curl_init( $url );
        curl_setopt_array( $ch, $options );
        $rough_content = curl_exec( $ch );
        $err     = curl_errno( $ch );
        $errmsg  = curl_error( $ch );
        $header  = curl_getinfo( $ch );
        curl_close( $ch );

        $header_content = substr($rough_content, 0, $header['header_size']);
        $body_content = trim(str_replace($header_content, '', $rough_content));
        $pattern = "#Set-Cookie:\\s+(?<cookie>[^=]+=[^;]+)#m"; 
        preg_match_all($pattern, $header_content, $matches); 
        $cookiesOut = implode("; ", $matches['cookie']);

        $header['errno']   = $err;
        $header['errmsg']  = $errmsg;
        $header['headers']  = $header_content;
        $header['content'] = $body_content;
        $header['cookies'] = $cookiesOut;
    return $header;
}

当我尝试打印第二个请求的整个响应时:

内容显然是空的。

Array ( [url] => https://www.google.com/a/MY_DOMAIN_NAME/ServiceLogin?service=wise&passive=1209600&continue=https://script.google.com/a/MY_DOMAIN_NAME/macros/s/AKfycbwg9-Y10kLyIJxGLYhpx9BnIu5f8AHs4qKEq1rSUoD-ugjsD3c/exec&followup=https://script.google.com/a/MY_DOMAIN_NAME/macros/s/AKfycbwg9-Y10kLyIJxGLYhpx9BnIu5f8AHs4qKEq1rSUoD-ugjsD3c/exec [content_type] => text/html; charset=UTF-8 [http_code] => 200 [header_size] => 511 [request_size] => 379 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.146943 [namelookup_time] => 0.001001 [connect_time] => 0.026204 [pretransfer_time] => 0.102405 [size_upload] => 0 [size_download] => 1839 [speed_download] => 12515 [speed_upload] => 0 [download_content_length] => 1839 [upload_content_length] => 0 [starttransfer_time] => 0.146158 [redirect_time] => 0 [redirect_url] => [primary_ip] => 172.217.16.68 [certinfo] => Array ( ) [request_header] => GET /a/MY_DOMAIN_NAME/ServiceLogin?service=wise&passive=1209600&continue=https://script.google.com/a/MY_DOMAIN_NAME/macros/s/AKfycbwg9-Y10kLyIJxGLYhpx9BnIu5f8AHs4qKEq1rSUoD-ugjsD3c/exec&followup=https://script.google.com/a/MY_DOMAIN_NAME/macros/s/AKfycbwg9-Y10kLyIJxGLYhpx9BnIu5f8AHs4qKEq1rSUoD-ugjsD3c/exec HTTP/1.1 Host: www.google.com Accept: */* Accept-Encoding: deflate, gzip Cookie: [errno] => 0 [errmsg] => [headers] => HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 X-Frame-Options: DENY Cache-control: no-cache, no-store Pragma: no-cache Expires: Mon, 01-Jan-1990 00:00:00 GMT Date: Sun, 08 Jul 2018 20:17:24 GMT X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Content-Length: 1839 Server: GSE Set-Cookie: GAPS=1:qc-OvEMCdZAhgMZ6MhkFoUwlPrOIGg:_W0RGhF378FPmC1G;Path=/a;Expires=Tue, 07-Jul-2020 20:17:24 GMT;Secure;HttpOnly;Priority=HIGH Alt-Svc: quic=":443"; ma=2592000; v="43,42,41,39,35" [content] =>
[cookies] => GAPS=1:qc-OvEMCdZAhgMZ6MhkFoUwlPrOIGg:_W0RGhF378FPmC1G )

编辑:

事实证明,该服务设置为仅供我访问。所以事件链现在更清楚了:我访问了服务,谷歌要求身份验证,由于我以所需用户身份登录浏览器,我立即被重定向到服务。一旦我在注销时在浏览器中运行 PHP 脚本,我就得到了 Google 登录页面。

我现在已经部署了服务供任何人访问,我可以在不重定向和从服务中获取内容的情况下访问服务。重定向行为的区别似乎是/a/druna.cz/. 没有它并且仍然只为我部署访问时,我在内容中获得登录页面 html 而无需重定向。有了它,它总是会导致重定向。实际网址是 https://script.google.com/a/druna.cz/macros/s/AKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k/exec

因此,即使通过更好的设置可以避免重定向,问题仍然存在 - 在需要身份验证(/a/druna.cz/存在)的情况下它如何强制重定向,有没有办法避免它(并且在 PHP 脚本中失败)?

标签: phpcurlgoogle-apps-script

解决方案


我使用第一个 URL https://script.google.com/a/druna.cz/macros/s/AKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k/exec在命令行上检查了您的代码

它打印了很多 HTML 并打印了“hello” 在 HTML 中有重要的语句“window.location.replace(redirectUrl);” 由于通过浏览器访问此 HTML,页面会重定向。当您登录浏览器窗口时,由于类似的 JS 代码,它可能会重定向到其他一些 url。

<!DOCTYPE html>
<html lang="en">
  <head>
  <meta charset="utf-8">
  <meta name="robots" content="noindex">
  <title>Sign in - Google Accounts</title>
  <meta http-equiv="refresh" content="1; url=https://www.google.com/accounts/AccountChooser?hd=druna.cz&amp;continue=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec&amp;followup=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec&amp;service=wise"></meta>
  </head>
  <body >
  <form id="hiddenget" action="https://www.google.com/accounts/AccountChooser?hd=druna.cz&amp;continue=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec&amp;followup=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec&amp;service=wise" method="get">
  <noscript>
  You should turn on Javascript support.
  <input type="submit" id="nojssubmit" value="Continue">
  </noscript>
</form>
  <script nonce="HobMA9FpZpT2/2X7NDFffIUgemA">
window.onload = function() {
  var redirectUrl = 'https:\x2F\x2Fwww.google.com\x2Faccounts\x2FAccountChooser?hd=druna.cz\x26continue=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec\x26followup=https%3A%2F%2Fscript.google.com%2Fa%2Fdruna.cz%2Fmacros%2Fs%2FAKfycbzo6Y_XiXHLZFuNEb2rB7GLVXbXhtBpCGo9AlL8ul-gITmvv6k%2Fexec\x26service=wise';
  var domain = 'druna.cz';
  var hash = window.location.hash;
  if (hash) {
  var match = hash.match(/[#&]Email=([^&]+)/);
  if (match) {
  redirectUrl += "&Email=" + match[1] + "@" + domain;
  }
  }
  window.location.replace(redirectUrl);
};
</script>
  </body>
</html>hello

推荐阅读