protected function doNotify($channel, array $events) { if (!count($events)) { return true; } $response = $this->http->run(array('url' => "{$this->baseUrl}/relayer/api/v1.0/" . rawurlencode($channel), 'method' => 'POST', 'body' => json_encode(array('events' => $events)), 'headers' => array('content-type' => 'application/json'))); return $response['code'] == 201; }
/** * Runs all the queries. */ public function run() { $http = new MultiHttpClient(array('reqTimeout' => $this->timeout, 'connTimeout' => 3)); $responses = $http->runMulti($this->getMultiHttpQueries($this->queries)); foreach ($responses as $index => $response) { $this->responses[$index] = $response; } $this->hasRun = true; }
/** * Delete an item. * * @param string $key * @return bool True if the item was deleted or not found, false on failure */ public function delete($key) { $req = ['method' => 'DELETE', 'url' => $this->url . rawurlencode($key)]; list($rcode, $rdesc, $rhdrs, $rbody, $rerr) = $this->client->run($req); if ($rcode === 200 || $rcode === 204 || $rcode === 205) { return true; } return $this->handleError("Failed to delete {$key}", $rcode, $rerr); }
/** * @return array|null Credential map */ protected function getAuthentication() { if ($this->authErrorTimestamp !== null) { if (time() - $this->authErrorTimestamp < 60) { return null; // failed last attempt; don't bother } else { // actually retry this time $this->authErrorTimestamp = null; } } // Session keys expire after a while, so we renew them periodically $reAuth = time() - $this->authSessionTimestamp > $this->authTTL; // Authenticate with proxy and get a session key... if (!$this->authCreds || $reAuth) { $this->authSessionTimestamp = 0; $cacheKey = $this->getCredsCacheKey($this->swiftUser); $creds = $this->srvCache->get($cacheKey); // credentials // Try to use the credential cache if (isset($creds['auth_token']) && isset($creds['storage_url'])) { $this->authCreds = $creds; // Skew the timestamp for worst case to avoid using stale credentials $this->authSessionTimestamp = time() - ceil($this->authTTL / 2); } else { // cache miss list($rcode, $rdesc, $rhdrs, $rbody, $rerr) = $this->http->run(array('method' => 'GET', 'url' => "{$this->swiftAuthUrl}/v1.0", 'headers' => array('x-auth-user' => $this->swiftUser, 'x-auth-key' => $this->swiftKey))); if ($rcode >= 200 && $rcode <= 299) { // OK $this->authCreds = array('auth_token' => $rhdrs['x-auth-token'], 'storage_url' => $rhdrs['x-storage-url']); $this->srvCache->set($cacheKey, $this->authCreds, ceil($this->authTTL / 2)); $this->authSessionTimestamp = time(); } elseif ($rcode === 401) { $this->onError(null, __METHOD__, array(), "Authentication failed.", $rcode); $this->authErrorTimestamp = time(); return null; } else { $this->onError(null, __METHOD__, array(), "HTTP return code: {$rcode}", $rcode); $this->authErrorTimestamp = time(); return null; } } // Ceph RGW does not use <account> in URLs (OpenStack Swift uses "/v1/<account>") if (substr($this->authCreds['storage_url'], -3) === '/v1') { $this->isRGW = true; // take advantage of strong consistency in Ceph } } return $this->authCreds; }
/** * Execute a set of virtual HTTP(S) requests concurrently * * A map of requests keys to response maps is returned. Each response map has: * - code : HTTP response code or 0 if there was a serious cURL error * - reason : HTTP response reason (empty if there was a serious cURL error) * - headers : <header name/value associative array> * - body : HTTP response body or resource (if "stream" was set) * - error : Any cURL error string * The map also stores integer-indexed copies of these values. This lets callers do: * @code * list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $responses[0]; * @endcode * * @param array $reqs Map of Virtual HTTP request maps * @return array $reqs Map of corresponding response values with the same keys/order * @throws Exception */ public function runMulti(array $reqs) { foreach ($reqs as $index => &$req) { if (isset($req[0])) { $req['method'] = $req[0]; // short-form unset($req[0]); } if (isset($req[1])) { $req['url'] = $req[1]; // short-form unset($req[1]); } $req['chain'] = []; // chain or list of replaced requests } unset($req); // don't assign over this by accident $curUniqueId = 0; $armoredIndexMap = []; // (original index => new index) $doneReqs = []; // (index => request) $executeReqs = []; // (index => request) $replaceReqsByService = []; // (prefix => index => request) $origPending = []; // (index => 1) for original requests foreach ($reqs as $origIndex => $req) { // Re-index keys to consecutive integers (they will be swapped back later) $index = $curUniqueId++; $armoredIndexMap[$origIndex] = $index; $origPending[$index] = 1; if (preg_match('#^(http|ftp)s?://#', $req['url'])) { // Absolute FTP/HTTP(S) URL, run it as normal $executeReqs[$index] = $req; } else { // Must be a virtual HTTP URL; resolve it list($prefix, $service) = $this->getMountAndService($req['url']); if (!$service) { throw new UnexpectedValueException("Path '{$req['url']}' has no service."); } // Set the URL to the mount-relative portion $req['url'] = substr($req['url'], strlen($prefix)); $replaceReqsByService[$prefix][$index] = $req; } } // Function to get IDs that won't collide with keys in $armoredIndexMap $idFunc = function () use(&$curUniqueId) { return $curUniqueId++; }; $rounds = 0; do { if (++$rounds > 5) { // sanity throw new Exception("Too many replacement rounds detected. Aborting."); } // Track requests executed this round that have a prefix/service. // Note that this also includes requests where 'response' was forced. $checkReqIndexesByPrefix = []; // Resolve the virtual URLs valid and qualified HTTP(S) URLs // and add any required authentication headers for the backend. // Services can also replace requests with new ones, either to // defer the original or to set a proxy response to the original. $newReplaceReqsByService = []; foreach ($replaceReqsByService as $prefix => $servReqs) { $service = $this->instances[$prefix]; foreach ($service->onRequests($servReqs, $idFunc) as $index => $req) { // Services use unique IDs for replacement requests if (isset($servReqs[$index]) || isset($origPending[$index])) { // A current or original request which was not modified } else { // Replacement request that will convert to original requests $newReplaceReqsByService[$prefix][$index] = $req; } if (isset($req['response'])) { // Replacement requests with pre-set responses should not execute unset($executeReqs[$index]); unset($origPending[$index]); $doneReqs[$index] = $req; } else { // Original or mangled request included $executeReqs[$index] = $req; } $checkReqIndexesByPrefix[$prefix][$index] = 1; } } // Update index of requests to inspect for replacement $replaceReqsByService = $newReplaceReqsByService; // Run the actual work HTTP requests foreach ($this->http->runMulti($executeReqs) as $index => $ranReq) { $doneReqs[$index] = $ranReq; unset($origPending[$index]); } $executeReqs = []; // Services can also replace requests with new ones, either to // defer the original or to set a proxy response to the original. // Any replacement requests executed above will need to be replaced // with new requests (eventually the original). The responses can be // forced by setting 'response' rather than actually be sent over the wire. $newReplaceReqsByService = []; foreach ($checkReqIndexesByPrefix as $prefix => $servReqIndexes) { $service = $this->instances[$prefix]; // $doneReqs actually has the requests (with 'response' set) $servReqs = array_intersect_key($doneReqs, $servReqIndexes); foreach ($service->onResponses($servReqs, $idFunc) as $index => $req) { // Services use unique IDs for replacement requests if (isset($servReqs[$index]) || isset($origPending[$index])) { // A current or original request which was not modified } else { // Replacement requests with pre-set responses should not execute $newReplaceReqsByService[$prefix][$index] = $req; } if (isset($req['response'])) { // Replacement requests with pre-set responses should not execute unset($origPending[$index]); $doneReqs[$index] = $req; } else { // Update the request in case it was mangled $executeReqs[$index] = $req; } } } // Update index of requests to inspect for replacement $replaceReqsByService = $newReplaceReqsByService; } while (count($origPending)); $responses = []; // Update $reqs to include 'response' and normalized request 'headers'. // This maintains the original order of $reqs. foreach ($reqs as $origIndex => $req) { $index = $armoredIndexMap[$origIndex]; if (!isset($doneReqs[$index])) { throw new UnexpectedValueException("Response for request '{$index}' is NULL."); } $responses[$origIndex] = $doneReqs[$index]['response']; } return $responses; }
public function testDelete() { $this->client->expects($this->once())->method('run')->with(['method' => 'DELETE', 'url' => 'http://test/rest/42xyz42'])->willReturn([200, 'OK', [], 'Done', 0]); $result = $this->bag->delete('42xyz42'); $this->assertTrue($result); }