Differential D19193 Diff 45972 src/applications/files/controller/PhabricatorFileImageProxyController.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/files/controller/PhabricatorFileImageProxyController.php
| Show All 38 Lines | public function handleRequest(AphrontRequest $request) { | ||||
| } | } | ||||
| $ttl = PhabricatorTime::getNow() + phutil_units('7 days in seconds'); | $ttl = PhabricatorTime::getNow() + phutil_units('7 days in seconds'); | ||||
| $external_request = id(new PhabricatorFileExternalRequest()) | $external_request = id(new PhabricatorFileExternalRequest()) | ||||
| ->setURI($img_uri) | ->setURI($img_uri) | ||||
| ->setTTL($ttl); | ->setTTL($ttl); | ||||
| $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | ||||
| $save_request = false; | |||||
| // Cache missed so we'll need to validate and download the image | // Cache missed so we'll need to validate and download the image | ||||
| try { | try { | ||||
| // Rate limit outbound fetches to make this mechanism less useful for | // Rate limit outbound fetches to make this mechanism less useful for | ||||
| // scanning networks and ports. | // scanning networks and ports. | ||||
| PhabricatorSystemActionEngine::willTakeAction( | PhabricatorSystemActionEngine::willTakeAction( | ||||
| array($viewer->getPHID()), | array($viewer->getPHID()), | ||||
| new PhabricatorFilesOutboundRequestAction(), | new PhabricatorFilesOutboundRequestAction(), | ||||
| 1); | 1); | ||||
| Show All 15 Lines | try { | ||||
| 'a file with MIME type "%s". You must specify the URI of a '. | 'a file with MIME type "%s". You must specify the URI of a '. | ||||
| 'valid image file.', | 'valid image file.', | ||||
| $uri, | $uri, | ||||
| $mime_type)); | $mime_type)); | ||||
| } else { | } else { | ||||
| $file->save(); | $file->save(); | ||||
| } | } | ||||
| $external_request->setIsSuccessful(true) | $external_request | ||||
| ->setFilePHID($file->getPHID()) | ->setIsSuccessful(1) | ||||
| ->save(); | ->setFilePHID($file->getPHID()); | ||||
| unset($unguarded); | |||||
| return $this->getExternalResponse($external_request); | $save_request = true; | ||||
| } catch (HTTPFutureHTTPResponseStatus $status) { | } catch (HTTPFutureHTTPResponseStatus $status) { | ||||
| $external_request->setIsSuccessful(false) | $external_request | ||||
| ->setIsSuccessful(0) | |||||
| ->setResponseMessage($status->getMessage()) | ->setResponseMessage($status->getMessage()) | ||||
| ->save(); | ->save(); | ||||
| return $this->getExternalResponse($external_request); | |||||
| $save_request = true; | |||||
| } catch (Exception $ex) { | } catch (Exception $ex) { | ||||
| // Not actually saving the request in this case | // Not actually saving the request in this case | ||||
| $external_request->setResponseMessage($ex->getMessage()); | $external_request->setResponseMessage($ex->getMessage()); | ||||
| return $this->getExternalResponse($external_request); | |||||
| } | } | ||||
| if ($save_request) { | |||||
| try { | |||||
| $external_request->save(); | |||||
| } catch (AphrontDuplicateKeyQueryException $ex) { | |||||
| // We may have raced against another identical request. If we did, | |||||
| // just throw our result away and use the winner's result. | |||||
| $external_request = $external_request->loadOneWhere( | |||||
| 'uriIndex = %s', | |||||
| PhabricatorHash::digestForIndex($img_uri)); | |||||
| if (!$external_request) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Hit duplicate key collision when saving proxied image, but '. | |||||
| 'failed to load duplicate row (for URI "%s").', | |||||
| $img_uri)); | |||||
| } | |||||
| } | |||||
| } | |||||
| unset($unguarded); | |||||
| return $this->getExternalResponse($external_request); | |||||
| } | } | ||||
| private function getExternalResponse( | private function getExternalResponse( | ||||
| PhabricatorFileExternalRequest $request) { | PhabricatorFileExternalRequest $request) { | ||||
| if ($request->getIsSuccessful()) { | if (!$request->getIsSuccessful()) { | ||||
| throw new Exception( | |||||
| pht( | |||||
| 'Request to "%s" failed: %s', | |||||
| $request->getURI(), | |||||
| $request->getResponseMessage())); | |||||
| } | |||||
| $file = id(new PhabricatorFileQuery()) | $file = id(new PhabricatorFileQuery()) | ||||
| ->setViewer(PhabricatorUser::getOmnipotentUser()) | ->setViewer(PhabricatorUser::getOmnipotentUser()) | ||||
| ->withPHIDs(array($request->getFilePHID())) | ->withPHIDs(array($request->getFilePHID())) | ||||
| ->executeOne(); | ->executeOne(); | ||||
| if (!$file) { | if (!$file) { | ||||
| throw new Exception(pht( | throw new Exception( | ||||
| pht( | |||||
| 'The underlying file does not exist, but the cached request was '. | 'The underlying file does not exist, but the cached request was '. | ||||
| 'successful. This likely means the file record was manually deleted '. | 'successful. This likely means the file record was manually '. | ||||
| 'by an administrator.')); | 'deleted by an administrator.')); | ||||
| } | |||||
| return id(new AphrontRedirectResponse()) | |||||
| ->setIsExternal(true) | |||||
| ->setURI($file->getViewURI()); | |||||
| } else { | |||||
| throw new Exception(pht( | |||||
| "The request to get the external file from '%s' was unsuccessful:\n %s", | |||||
| $request->getURI(), | |||||
| $request->getResponseMessage())); | |||||
| } | } | ||||
| return id(new AphrontAjaxResponse()) | |||||
| ->setContent( | |||||
| array( | |||||
| 'imageURI' => $file->getViewURI(), | |||||
| )); | |||||
| } | } | ||||
| } | } | ||||