1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 21:40:55 +01:00

Make "Range" HTTP header work for Celerity static resource requests

Summary:
Ref T7567. In T8266 I fixed a bunch of obscure "Range" issues, but only for file downloads -- not for Celerity.

Extend all that stuff to Celerity, which is fortunately much easier.

I believe this will fix Conpherence sounds in Safari.

Test Plan:
  - Wrote out an HTTP request in a text file with `Range: bytes=0-1` and similar, piped it to localhost with `cat request.txt | nc localhost 80`, saw server return appropriate range responses consistent with file behavior after T8266, which all seems to work.
  - Also did that for files to try to make sure I wasn't breaking anything.

Reviewers: chad, amckinley

Reviewed By: chad

Maniphest Tasks: T7567

Differential Revision: https://secure.phabricator.com/D17724
This commit is contained in:
epriestley 2017-04-18 13:17:39 -07:00
parent ece9579d25
commit b479941ceb
3 changed files with 51 additions and 21 deletions

View file

@ -139,4 +139,29 @@ final class AphrontFileResponse extends AphrontResponse {
return $this->getCompressResponse(); return $this->getCompressResponse();
} }
public function parseHTTPRange($range) {
$begin = null;
$end = null;
$matches = null;
if (preg_match('/^bytes=(\d+)-(\d*)$/', $range, $matches)) {
// Note that the "Range" header specifies bytes differently than
// we do internally: the range 0-1 has 2 bytes (byte 0 and byte 1).
$begin = (int)$matches[1];
// The "Range" may be "200-299" or "200-", meaning "until end of file".
if (strlen($matches[2])) {
$range_end = (int)$matches[2];
$end = $range_end + 1;
} else {
$range_end = null;
}
$this->setHTTPResponseCode(206);
$this->setRange($begin, $range_end);
}
return array($begin, $end);
}
} }

View file

@ -104,9 +104,30 @@ abstract class CelerityResourceController extends PhabricatorController {
} }
$response = id(new AphrontFileResponse()) $response = id(new AphrontFileResponse())
->setMimeType($type_map[$type]);
$range = AphrontRequest::getHTTPHeader('Range');
if (strlen($range)) {
$response->setContentLength(strlen($data));
list($range_begin, $range_end) = $response->parseHTTPRange($range);
if ($range_begin !== null) {
if ($range_end !== null) {
$data = substr($data, $range_begin, ($range_end - $range_begin));
} else {
$data = substr($data, $range_begin);
}
}
$response->setContentIterator(array($data));
} else {
$response
->setContent($data) ->setContent($data)
->setMimeType($type_map[$type])
->setCompressResponse(true); ->setCompressResponse(true);
}
// NOTE: This is a piece of magic required to make WOFF fonts work in // NOTE: This is a piece of magic required to make WOFF fonts work in
// Firefox and IE. Possibly we should generalize this more. // Firefox and IE. Possibly we should generalize this more.

View file

@ -62,24 +62,8 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
// an initial request for bytes 0-1 of the audio file, and things go south // an initial request for bytes 0-1 of the audio file, and things go south
// if we can't respond with a 206 Partial Content. // if we can't respond with a 206 Partial Content.
$range = $request->getHTTPHeader('range'); $range = $request->getHTTPHeader('range');
if ($range) { if (strlen($range)) {
$matches = null; list($begin, $end) = $response->parseHTTPRange($range);
if (preg_match('/^bytes=(\d+)-(\d*)$/', $range, $matches)) {
// Note that the "Range" header specifies bytes differently than
// we do internally: the range 0-1 has 2 bytes (byte 0 and byte 1).
$begin = (int)$matches[1];
// The "Range" may be "200-299" or "200-", meaning "until end of file".
if (strlen($matches[2])) {
$range_end = (int)$matches[2];
$end = $range_end + 1;
} else {
$range_end = null;
}
$response->setHTTPResponseCode(206);
$response->setRange($begin, $range_end);
}
} }
$is_viewable = $file->isViewableInBrowser(); $is_viewable = $file->isViewableInBrowser();