diff --git a/lib/filelib.php b/lib/filelib.php index a32b36fd994..12990e79eba 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3082,6 +3082,10 @@ class curl { * private callback function * Formatting HTTP Response Header * + * We only keep the last headers returned. For example during a redirect the + * redirect headers will not appear in {@link self::getResponse()}, if you need + * to use those headers, refer to {@link self::get_raw_response()}. + * * @param resource $ch Apparently not used * @param string $header * @return int The strlen of the header @@ -3090,15 +3094,17 @@ class curl { $this->rawresponse[] = $header; if (trim($header, "\r\n") === '') { - if ($this->responsefinished) { - // Multiple headers means redirect, keep just the latest one. - $this->response = array(); - return strlen($header); - } + // This must be the last header. $this->responsefinished = true; } if (strlen($header) > 2) { + if ($this->responsefinished) { + // We still have headers after the supposedly last header, we must be + // in a redirect so let's empty the response to keep the last headers. + $this->responsefinished = false; + $this->response = array(); + } list($key, $value) = explode(" ", rtrim($header, "\r\n"), 2); $key = rtrim($key, ':'); if (!empty($this->response[$key])) { @@ -3402,9 +3408,6 @@ class curl { } } - $this->responsefinished = false; - $this->response = array(); - curl_setopt($curl, CURLOPT_URL, $redirecturl); $ret = curl_exec($curl); diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 3f9f041db63..84b3f10a91d 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -399,6 +399,79 @@ class core_filelib_testcase extends advanced_testcase { $CFG->proxybypass = $oldproxybypass; } + public function test_curl_response_headers() { + + // Test 404 request. + $curl = new curl(); + $contents = $curl->get($this->getExternalTestFileUrl('/i.do.not.exist')); + $response = $curl->getResponse(); + $this->assertSame('404 Not Found', reset($response)); + $this->assertSame(0, $curl->get_errno()); + + $testhtml = $this->getExternalTestFileUrl('/test.html'); + + // Test standard request. + $curl = new curl(); + $contents = $curl->get($testhtml); + $response = $curl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $curl->get_errno()); + + $testurl = $this->getExternalTestFileUrl('/test_relative_redir.php'); + + // Test a redirect without follow location. + $curl = new curl(); + $contents = $curl->get("$testurl?redir=3", array(), array('CURLOPT_FOLLOWLOCATION'=>0)); + $response = $curl->getResponse(); + $this->assertSame('302 Found', reset($response)); + $this->assertSame(0, $curl->get_errno()); + + // Test a redirect without follow location and emulated redirect. + $curl = new curl(); + $curl->emulateredirects = true; + $contents = $curl->get("$testurl?redir=3", array(), array('CURLOPT_FOLLOWLOCATION'=>0)); + $response = $curl->getResponse(); + $this->assertSame('302 Found', reset($response)); + $this->assertSame(0, $curl->get_errno()); + + // Test a redirect. + $curl = new curl(); + $contents = $curl->get("$testurl?type=302"); + $response = $curl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $curl->get_errno()); + $this->assertSame(1, $curl->info['redirect_count']); + $this->assertSame('done', $contents); + + // Test a redirect with emulated redirect. + $curl = new curl(); + $curl->emulateredirects = true; + $contents = $curl->get("$testurl?type=302"); + $response = $curl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $curl->get_errno()); + $this->assertSame('done', $contents); + + $testpost = $this->getExternalTestFileUrl('/test_post.php'); + + // Test post request. + $curl = new curl(); + $contents = $curl->post($testpost, 'data=moodletest'); + $response = $curl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $curl->get_errno()); + $this->assertSame('OK', $contents); + + // Test 100 requests. + $curl = new curl(); + $curl->setHeader('Expect: 100-continue'); + $contents = $curl->post($testpost, 'data=moodletest'); + $response = $curl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $curl->get_errno()); + $this->assertSame('OK', $contents); + } + /** * Testing prepare draft area *