diff --git a/typo3/sysext/core/Classes/Utility/GeneralUtility.php b/typo3/sysext/core/Classes/Utility/GeneralUtility.php
index d2d11562be053363aca3d43d57fad7746781e153..769dca7c764dd6a8fd812ba4d361d40d40f18b74 100644
--- a/typo3/sysext/core/Classes/Utility/GeneralUtility.php
+++ b/typo3/sysext/core/Classes/Utility/GeneralUtility.php
@@ -2418,14 +2418,17 @@ class GeneralUtility {
 				}
 				return FALSE;
 			}
+
+			$followLocationSucceeded = @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+
 			curl_setopt($ch, CURLOPT_URL, $url);
-			curl_setopt($ch, CURLOPT_HEADER, $includeHeader ? 1 : 0);
+			curl_setopt($ch, CURLOPT_HEADER, !$followLocationSucceeded || $includeHeader ? 1 : 0);
 			curl_setopt($ch, CURLOPT_NOBODY, $includeHeader == 2 ? 1 : 0);
 			curl_setopt($ch, CURLOPT_HTTPGET, $includeHeader == 2 ? 'HEAD' : 'GET');
 			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 			curl_setopt($ch, CURLOPT_FAILONERROR, 1);
 			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, max(0, (int)$GLOBALS['TYPO3_CONF_VARS']['SYS']['curlTimeout']));
-			$followLocation = @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+
 			if (is_array($requestHeaders)) {
 				curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
 			}
@@ -2443,21 +2446,42 @@ class GeneralUtility {
 				}
 			}
 			$content = curl_exec($ch);
+			$curlInfo = curl_getinfo($ch);
+
+			if (!$followLocationSucceeded) {
+				// Check if we need to do redirects
+				if ($curlInfo['http_code'] >= 300 && $curlInfo['http_code'] < 400) {
+					$locationUrl = $curlInfo['redirect_url'];
+					if (!$locationUrl) {
+						// Some curllib versions do not return redirect_url. Examine headers.
+						$locationUrl = self::getRedirectUrlFromHttpHeaders($content);
+					}
+					if ($locationUrl) {
+						$content = self::getUrl($locationUrl, $includeHeader, $requestHeaders, $report);
+						$followLocationSucceeded = TRUE;
+					} else {
+						// Failure: we got a redirection status code but not the URL to redirect to.
+						$content = FALSE;
+					}
+				}
+				if ($content && !$includeHeader) {
+					$content = self::stripHttpHeaders($content);
+				}
+			}
+
 			if (isset($report)) {
-				if ($content === FALSE) {
+				if (!$followLocationSucceeded && $curlInfo['http_code'] >= 300 && $curlInfo['http_code'] < 400) {
+					$report['http_code'] = $curlInfo['http_code'];
+					$report['content_type'] = $curlInfo['content_type'];
+					$report['error'] = CURLE_GOT_NOTHING;
+					$report['message'] = 'Expected "Location" header but got nothing.';
+				} elseif ($content === FALSE) {
 					$report['error'] = curl_errno($ch);
 					$report['message'] = curl_error($ch);
-				} else {
-					$curlInfo = curl_getinfo($ch);
-					// We hit a redirection but we couldn't follow it
-					if (!$followLocation && $curlInfo['status'] >= 300 && $curlInfo['status'] < 400) {
-						$report['error'] = -1;
-						$report['message'] = 'Couldn\'t follow location redirect (PHP configuration option open_basedir is in effect).';
-					} elseif ($includeHeader) {
-						// Set only for $includeHeader to work exactly like PHP variant
-						$report['http_code'] = $curlInfo['http_code'];
-						$report['content_type'] = $curlInfo['content_type'];
-					}
+				} elseif ($includeHeader) {
+					// Set only for $includeHeader to work exactly like PHP variant
+					$report['http_code'] = $curlInfo['http_code'];
+					$report['content_type'] = $curlInfo['content_type'];
 				}
 			}
 			curl_close($ch);
@@ -2557,6 +2581,45 @@ Connection: close
 		return $content;
 	}
 
+	/**
+	 * Parses HTTP headers and returns the content of the "Location" header
+	 * or the empty string if no such header found.
+	 *
+	 * @param string $content
+	 * @return string
+	 */
+	static protected function getRedirectUrlFromHttpHeaders($content) {
+		$result = '';
+		$headers = explode("\r\n", $content);
+		foreach ($headers as $header) {
+			if ($header == '') {
+				break;
+			}
+			if (preg_match('/^\s*Location\s*:/i', $header)) {
+				list(, $result) = self::trimExplode(':', $header, FALSE, 2);
+				if ($result) {
+					$result = self::locationHeaderUrl($result);
+				}
+				break;
+			}
+		}
+		return $result;
+	}
+
+	/**
+	 * Strips HTTP headers from the content.
+	 *
+	 * @param string $content
+	 * @return string
+	 */
+	static protected function stripHttpHeaders($content) {
+		$headersEndPos = strpos($content, "\r\n\r\n");
+		if ($headersEndPos) {
+			$content = substr($content, $headersEndPos + 4);
+		}
+		return $content;
+	}
+
 	/**
 	 * Writes $content to the file $file
 	 *
diff --git a/typo3/sysext/core/Tests/Unit/Utility/Fixtures/GeneralUtilityFixture.php b/typo3/sysext/core/Tests/Unit/Utility/Fixtures/GeneralUtilityFixture.php
index 4e99ec14af9d19ec4ef3a6edd909582f83f992ed..97c1a41ca6512d7ab285d875b3c5ff02d30581c6 100644
--- a/typo3/sysext/core/Tests/Unit/Utility/Fixtures/GeneralUtilityFixture.php
+++ b/typo3/sysext/core/Tests/Unit/Utility/Fixtures/GeneralUtilityFixture.php
@@ -53,5 +53,24 @@ class GeneralUtilityFixture extends GeneralUtility {
 		return FALSE;
 	}
 
+	/**
+	 * Parses HTTP headers and returns the content of the "Location" header
+	 * or the empty string if no such header found.
+	 *
+	 * @param string $content
+	 * @return string
+	 */
+	static public function getRedirectUrlFromHttpHeaders($content) {
+		return parent::getRedirectUrlFromHttpHeaders($content);
+	}
 
+	/**
+	 * Strips HTTP headers from the content.
+	 *
+	 * @param string $content
+	 * @return string
+	 */
+	static public function stripHttpHeaders($content) {
+		return parent::stripHttpHeaders($content);
+	}
 }
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php b/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php
index bc2456d329c02c671efcf8165578c765a98acb3a..190d992d59e82709713b5b62e355f35da4d1268a 100644
--- a/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php
+++ b/typo3/sysext/core/Tests/Unit/Utility/GeneralUtilityTest.php
@@ -4511,9 +4511,48 @@ text with a ' . $urlMatch . '$|s'),
 	 * @param string $input Text to recognise URLs from
 	 * @param string $expected Text with correctly detected URLs
 	 */
-	public function substUrlsInPlainText($input, $expectedPreg) {
+	public function substUrlsInPlainText($input, $expected) {
 		$GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array(), array(), '', FALSE);
-		$this->assertTrue(preg_match($expectedPreg, Utility\GeneralUtility::substUrlsInPlainText($input, 1, 'http://example.com/index.php')) == 1);
+		$this->assertTrue(preg_match($expected, Utility\GeneralUtility::substUrlsInPlainText($input, 1, 'http://example.com/index.php')) == 1);
 	}
 
+	/**
+	 * @return array
+	 */
+	public function getRedirectUrlFromHttpHeadersDataProvider() {
+		return array(
+			'Extracts redirect URL from Location header' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nLocation: http://example.com/\r\nX-pad: avoid browser bug\r\n\r\nLocation: test\r\n", 'http://example.com/'),
+			'Returns empty string if no Location is found in header' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nLocation: test\r\n", ''),
+		);
+	}
+
+	/**
+	 * @param string $httpResponse
+	 * @param string $expected
+	 * @test
+	 * @dataProvider getRedirectUrlFromHttpHeadersDataProvider
+	 */
+	public function getRedirectUrlReturnsRedirectUrlFromHttpResponse($httpResponse, $expected) {
+		$this->assertEquals($expected, GeneralUtilityFixture::getRedirectUrlFromHttpHeaders($httpResponse));
+	}
+
+	/**
+	 * @return array
+	 */
+	public function getStripHttpHeadersDataProvider() {
+		return array(
+			'Simple content' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nHello, world!", 'Hello, world!'),
+			'Content with multiple returns' => array("HTTP/1.0 302 Redirect\r\nServer: Apache\r\nX-pad: avoid browser bug\r\n\r\nHello, world!\r\n\r\nAnother hello here!", "Hello, world!\r\n\r\nAnother hello here!"),
+		);
+	}
+
+	/**
+	 * @param string $httpResponse
+	 * @param string $expected
+	 * @test
+	 * @dataProvider getStripHttpHeadersDataProvider
+	 */
+	public function stripHttpHeadersStripsHeadersFromHttpResponse($httpResponse, $expected) {
+		$this->assertEquals($expected, GeneralUtilityFixture::stripHttpHeaders($httpResponse));
+	}
 }