我有一个安装了curl的托管服务器,但没有安装http_post_data()pecl。
我正在尝试将此(工作)http_post_data()代码翻译为curl:
$responseString = @http_post_data("http://" . $this->username . ":" . $this->password ."@" . $this->webserviceHost . $this->requestUriBase .$request,
$requestString,
array('http_auth' => $this->username . ":" . $this->password, 'headers' => array('Content-Type' => 'text/xml')));
我试过了:
$url = "http://" . $this->username . ":" . $this->password ."@" . $this->webserviceHost . $this->requestUriBase .$request;
curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Accept: application/xml', 'Content-Type: application/xml'));
curl_setopt($this->curl, CURLOPT_URL, $url);
curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt(CURLOPT_USERPWD, "[$this->username]:[$this->password]");
curl_setopt ($this->curl, CURLOPT_POST, true);
curl_setopt ($this->curl, CURLOPT_POSTFIELDS, array($requestString));
$content = curl_exec($this->curl);
...并且失败:无法连接到主机
什么是正确的代码?
答案 0 :(得分:2)
这是一个允许您使用未经修改的现有代码的函数:
if (!function_exists('http_post_data')) {
function http_post_data ($url, $data, $options) {
// Construct the URL with the auth stripped out
$urlParts = parse_url($url);
$urlToUse = $urlParts['scheme'].'://'.$urlParts['host'];
if (isset($urlParts['port'])) $urlToUse .= ':'.$urlParts['port'];
$urlToUse .= $urlParts['path'];
if (isset($urlParts['query'])) $urlToUse .= '?'.$urlParts['query'];
// Convert headers to a format cURL will like
$headers = array();
if (isset($options['headers'])) {
foreach ($options['headers'] as $name => $val) {
$headers[] = "$name: $val";
}
}
// Initialise cURL with the modified URL
$ch = curl_init($urlToUse);
// We want the function to return the response as a string
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
// Set the method to POST and set the body data
curl_setopt ($ch, CURLOPT_POST, TRUE);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $data); // Wrapping this in an array() is definitely wrong, given that the content-type is xml
// Set the auth details if specified
if (isset($urlParts['user'], $urlParts['pass'])) {
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); // It's probably best to allow any auth method, unless you know the server ONLY supports basic
curl_setopt($ch, CURLOPT_USERPWD, $urlParts['user'].':'.$urlParts['pass']); // The square brackets are not required and will be treated as part of the username/password
}
// Set any extra headers
if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
// Send the request and return the result:
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
此函数仅实现您在原始代码中使用的http_post_data()
选项 - 也可以使用cURL实现其他功能,但我没有使用不必要的实现来扩展上述代码他们如果没有做太多错误检查,特别是在验证提供的URL方面,那么您可能希望添加一些额外的清理。
此功能包含在if (!function_exists())
中,以便您将代码放在任何地方。它不会与可用的本机功能发生冲突。
答案 1 :(得分:1)
要配置和执行CURL请求,我建议使用以下格式:
# in curl URL is scheme://hostname/rest, and hostname != authority
# (authority is hostname plus port and with user/pass in front)
$url = sprintf('http://%s/%s', $this->webserviceHost
, $this->requestUriBase . $request);
$options = array(
CURLOPT_HTTPHEADER => array(
'Accept: application/xml',
'Content-Type: application/xml',
),
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
# don't use the brackets []
CURLOPT_USERPWD => $this->username . ':' . $this->password,
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $requestString,
CURLOPT_RETURNTRANSFER => TRUE,
);
$this->curl = curl_init($url);
$r = curl_ setopt_ array($this->curl, $options);
if (!$r) throw new Exception('Failed to setup options.');
$content = curl_exec($this->curl); # This needs CURLOPT_RETURNTRANSFER => TRUE
我不确定 CURLOPT_POSTFIELDS
,因为您没有指定$requestString
包含的内容。上面的设置很可能是错误的。见curl POST format for CURLOPT_POSTFIELDS。
修改:您已通过http_post_data
指定了
包含预编码后期数据的字符串
Curl也支持这一点,只是不传递为数组,将其作为字符串传递:
CURLOPT_POSTFIELDS => $requestString,
答案 2 :(得分:0)
尝试从网址中删除用户名和密码,并使用不带括号的CURLOPT_USERPWD:
curl_setopt(CURLOPT_USERPWD, "$this->username:$this->password");
答案 3 :(得分:0)
您的网址不应包含用户名和密码 - 当您这样做时,curl会将其解释为主机名的一部分。
因此错误“无法连接到主机”。
您已经通过设置USERPWD选项来包含身份验证信息。