卷曲跟随位置错误

emb*_*ded 15 php curl

我收到此错误消息:

在safe_mode或设置了open_basedir时,无法激活CURLOPT_FOLLOWLOCATION.

safe_mode在我的网络托管上关闭.

open_basedir是"".

我该如何解决这个问题?

dol*_*men 13

解决方法是在PHP代码中实现重定向.

这是我自己的实现.它有两个已知的限制:

  1. 它会强迫 CURLOPT_RETURNTRANSFER
  2. 它与...不相容 CURLOPT_HEADERFUNCTION

代码:

function curl_exec_follow(/*resource*/ &$ch, /*int*/ $redirects = 20, /*bool*/ $curlopt_header = false) {
    if ((!ini_get('open_basedir') && !ini_get('safe_mode')) || $redirects < 1) {
        curl_setopt($ch, CURLOPT_HEADER, $curlopt_header);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $redirects > 0);
        curl_setopt($ch, CURLOPT_MAXREDIRS, $redirects);
        return curl_exec($ch);
    } else {
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FORBID_REUSE, false);

        do {
            $data = curl_exec($ch);
            if (curl_errno($ch))
                break;
            $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if ($code != 301 && $code != 302)
                break;
            $header_start = strpos($data, "\r\n")+2;
            $headers = substr($data, $header_start, strpos($data, "\r\n\r\n", $header_start)+2-$header_start);
            if (!preg_match("!\r\n(?:Location|URI): *(.*?) *\r\n!", $headers, $matches))
                break;
            curl_setopt($ch, CURLOPT_URL, $matches[1]);
        } while (--$redirects);
        if (!$redirects)
            trigger_error('Too many redirects. When following redirects, libcurl hit the maximum amount.', E_USER_WARNING);
        if (!$curlopt_header)
            $data = substr($data, strpos($data, "\r\n\r\n")+4);
        return $data;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在我的情况下,我需要将`&& $ code!= 303`(参见其他)添加到do循环中的if条件,以复制我的`CURLOPT_FOLLOWLOCATION = true`行为. (3认同)

Vol*_*erK 5

打印此警告消息的唯一位置是ext/curl/interface.c

if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
  if (Z_LVAL_PP(zvalue) != 0) {
    php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set");
    RETVAL_FALSE;
    return 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

从if条件可以看出,必须启用open_basedir或safe_mode.

  • 您可以使用`curl_getinfo($ ch,CURLINFO_HTTP_CODE)`,如果它返回301或302,则获取Location:标头. (4认同)