-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
It is not possible to get and forward all headers having multiple values of a response when performing a CURLRequest.
My experience was with 'set-cookie' header, but after investigating it was pretty obvious that the CURLRequest (and probably other involved or related classes) will only retain the last value of headers with the same name and in case of redirection trigger ErrorException: Header may not contain more than a single header, new line detected (SYSTEMPATH/HTTP/ResponseTrait.php at line 471).
The following fixed the issue for me:
System\HTTP\CURLRequest
protected function parseOptions(array $options)
{
if (array_key_exists('baseURI', $options)) {
$this->baseURI = $this->baseURI->setURI($options['baseURI']);
unset($options['baseURI']);
}
if (array_key_exists('headers', $options) && is_array($options['headers'])) {
foreach ($options['headers'] as $name => $value) {
// my adjustment
if($this->hasHeader($name)) {
$this->appendHeader($name, $value);
} else {
$this->setHeader($name, $value);
}
// end my adjustment
}
unset($options['headers']);
}
...System\HTTP\ResponseTrait
public function sendHeaders()
{
// Have the headers already been sent?
if ($this->pretend || headers_sent()) {
return $this;
}
// Per spec, MUST be sent with each request, if possible.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
if (! isset($this->headers['Date']) && PHP_SAPI !== 'cli-server') {
$this->setDate(DateTime::createFromFormat('U', (string) time()));
}
// HTTP Status
header(sprintf('HTTP/%s %s %s', $this->getProtocolVersion(), $this->getStatusCode(), $this->getReason()), true, $this->getStatusCode());
// Send all of our headers
foreach (array_keys($this->getHeaders()) as $name) {
// my adjustment
$headerValue = $this->getHeader($name)->getValue();
if(is_array($headerValue)) {
foreach($headerValue as $h_value) {
header($name . ': ' . $h_value, false, $this->getStatusCode());
}
} else {
header($name . ': ' . $this->getHeaderLine($name), false, $this->getStatusCode());
}
// end my adjustment
}
return $this;
}CodeIgniter 4 version
4.1.3
Affected module(s)
System\HTTP\CURLRequest
System\HTTP\ResponseTrait
probably some of the other classes as well
Expected behavior, and steps to reproduce if appropriate
- Perform a CURLRequest
- Obtain response with multiple values for i.e. 'set-cookie' header: expected - all values, obtained - the last value
- Redirect to endpoint while passing all 'set-cookie' headers: expected - redirection OK, obtained - error
Context
All