diff --git a/src/Apis/v1_0.php b/src/Apis/v1_0.php index 73edc6c..dd5feed 100644 --- a/src/Apis/v1_0.php +++ b/src/Apis/v1_0.php @@ -37,47 +37,67 @@ final class v1_0 implements \Uiharu\IApi { } public function register(HttpFx $router): void { - $router->get('/metadata', [$this, 'handleGET']); - $router->post('/metadata', [$this, 'handlePOST']); + $router->get('/metadata', [$this, 'getMetadata']); + $router->post('/metadata', [$this, 'postMetadata']); + $router->get('/metadata/batch', [$this, 'getMetadataBatch']); + $router->post('/metadata/batch', [$this, 'postMetadataBatch']); } - public function handleGET($response, $request) { + public function getMetadata($response, $request) { if($request->getMethod() === 'HEAD') { $response->setTypeJson(); return; } - return $this->handler( + return $this->handleMetadata( $response, $request, (string)$request->getParam('url') ); } - public function handlePOST($response, $request) { + public function postMetadata($response, $request) { if(!$request->isStreamContent()) return 400; - return $this->handler( + return $this->handleMetadata( $response, $request, $request->getContent()->getStream()->read(1000) ); } - private function handler($response, $request, string $targetUrl) { - $sw = Stopwatch::startNew(); - - $resp = new stdClass; - $response->setTypeJson(); - - if(empty($targetUrl)) { - $response->setStatusCode(400); - return $resp; + public function getMetadataBatch($response, $request) { + if($request->getMethod() === 'HEAD') { + $response->setTypeJson(); + return; } + return $this->handleMetadataBatch( + $response, $request, + $request->getParam('url', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY) + ); + } + + public function postMetadataBatch($response, $request) { + if(!$request->isFormContent()) + return 400; + + return $this->handleMetadataBatch( + $response, $request, + $request->getContent()->getParam('url', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY) + ); + } + + private function metadataLookup(string $targetUrl, bool $enableCache, bool $includeRawResult) { + $sw = Stopwatch::startNew(); + $resp = new stdClass; + + if(empty($targetUrl)) + return 400; + try { $parsedUrl = Url::parse($targetUrl); } catch(InvalidArgumentException $ex) { - $response->setStatusCode(400); + $resp->status = 400; $resp->error = 'metadata:uri'; return $resp; } @@ -90,9 +110,6 @@ final class v1_0 implements \Uiharu\IApi { $urlHash = $parsedUrl->calculateHash(false); - $enableCache = !UIH_DEBUG || $request->hasParam('_cache'); - $includeRawResult = UIH_DEBUG || $request->hasParam('include_raw'); - if($enableCache) { $cacheFetch = $this->db->prepare('SELECT `metadata_resp` FROM `uih_metadata_cache` WHERE `metadata_url` = UNHEX(?) AND `metadata_created` > NOW() - INTERVAL 10 MINUTE'); $cacheFetch->addParameter(1, $urlHash); @@ -213,12 +230,12 @@ final class v1_0 implements \Uiharu\IApi { $resp->dbg_media_info = $result->getMediaInfo(); } } catch(Exception $ex) { + $resp->status = 500; $resp->error = 'metadata:lookup'; if(UIH_DEBUG) { $resp->dbg_msg = $ex->getMessage(); $resp->dbg_ex = (string)$ex; } - $response->setStatusCode(500); return $resp; } @@ -232,8 +249,71 @@ final class v1_0 implements \Uiharu\IApi { } if(!empty($respJson)) - $response->setContent($respJson); - else - return $resp; + return $respJson; + + return $resp; + } + + private function handleMetadata($response, $request, string $targetUrl) { + $enableCache = !UIH_DEBUG || $request->hasParam('_cache'); + $includeRawResult = UIH_DEBUG || $request->hasParam('include_raw'); + + $result = $this->metadataLookup($targetUrl, $enableCache, $includeRawResult); + if(is_int($result)) + return $result; + + if(is_object($result)) { + if(!empty($result->status)) + $response->setStatusCode($result->status); + } elseif(is_string($result)) { + $response->setTypeJson(); + } + + return $result; + } + + private function handleMetadataBatch($response, $request, array $urls) { + $sw = Stopwatch::startNew(); + + if(count($urls) > 20) + return 400; + + $enableCache = !UIH_DEBUG || $request->hasParam('_cache'); + $includeRawResult = UIH_DEBUG || $request->hasParam('include_raw'); + + $handled = []; + $results = []; + + foreach($urls as $url) { + if(!is_string($url)) + continue; + + $cleanUrl = trim($url, '/?&# '); + if(in_array($cleanUrl, $handled)) + continue; + $handled[] = $cleanUrl; + + $result = $this->metadataLookup($url, $enableCache, $includeRawResult); + if(is_int($result)) { + $status = $result; + $result = new stdClass; + $result->status = $status; + $result->error = 'batch:status'; + } elseif(is_string($result)) { + $result = json_decode($result); + } + + $results[] = [ + 'url' => $url, + 'info' => $result, + ]; + } + + $sw->stop(); + + return [ + 'took' => $sw->getElapsedTime() / 1000, + 'results' => $results, + ]; } }