/** * Saves user data to the Management API. This operates as both insert and * update. * * If user's email doesn't look valid (must contain @), a * ParameterException is thrown. * * @param bool|null $force_update * If false, assume that this is a new instance. * If true, assume that this is an update to an existing instance. * If null, try an update, and if that fails, try an insert. * @param string|null $old_email * If the developer's email has changed, this field must contain the * previous email value. * * @throws \Apigee\Exceptions\ParameterException */ public function save($force_update = false, $old_email = null) { // See if we need to brute-force this. if ($force_update === null) { try { $this->save(true, $old_email); } catch (ResponseException $e) { if ($e->getCode() == 404) { // Update failed because dev doesn't exist. // Try insert instead. $this->save(false, $old_email); } else { // Some other response error. throw $e; } } return; } if (!$this->validateUser()) { $message = 'Developer requires valid-looking email address, firstName, lastName and userName.'; throw new ParameterException($message); } if (empty($old_email)) { $old_email = $this->email; } $payload = array('email' => $this->email, 'userName' => $this->userName, 'firstName' => $this->firstName, 'lastName' => $this->lastName); if (count($this->attributes) > 0) { $payload['attributes'] = array(); $i = 0; foreach ($this->attributes as $name => $value) { $i++; if ($i > self::MAX_ATTRIBUTE_COUNT && $this->pagingEnabled) { // This truncation occurs silently; should we throw an exception? break; } $payload['attributes'][] = array('name' => $name, 'value' => $value); } } $url = null; if ($force_update || $this->createdAt) { if ($this->developerId) { $payload['developerId'] = $this->developerId; } $url = rawurlencode($old_email); } // Save our desired status for later. $cached_status = $this->status; if ($force_update) { $this->put($url, $payload); } else { $this->post($url, $payload); } self::loadFromResponse($this, $this->responseObj); // We must cache the DebugData from the developer-save call so that // we can make it available to clients AFTER the "action" call below. $responseData = DebugData::toArray(); // If status has changed, we must directly change it with a separate // POST call, because Edge will ignore a 'status' member in the // app-save payload. // We must also do this when creating a developer ex nihilo in order // to set initial status. Otherwise new developer will have default // status, which is generally 'approved'. $this->post($this->email . '?action=' . $cached_status); $this->status = $cached_status; // Restore DebugData from cached response. DebugData::fromArray($responseData); }
private function exec(\Guzzle\Http\Message\RequestInterface $request) { $start = microtime(true); $this->responseCode = 0; // Get snapshot of request headers. $request_headers = $request->getRawHeaders(); // Mask authorization for logs. $request_headers = preg_replace('!\\nAuthorization: (Basic|Digest) [^\\r\\n]+\\r!i', "\nAuthorization: \$1 [**masked**]\r", $request_headers); try { $response = $request->send(); } catch (\Guzzle\Http\Exception\BadResponseException $e) { $response = $e->getResponse(); } catch (\Guzzle\Http\Exception\CurlException $e) { // Timeouts etc. DebugData::$raw = ''; DebugData::$code = $e->getErrorNo(); DebugData::$code_status = $e->getError(); DebugData::$code_class = 0; DebugData::$exception = $e->getMessage(); DebugData::$opts = array('request_headers' => $request_headers); DebugData::$data = null; $exception = new ResponseException($e->getError(), $e->getErrorNo(), $request->getUrl(), DebugData::$opts); $exception->requestObj = $request; // Log Exception $headers_array = $request->getHeaders(); unset($headers_array['Authorization']); $headerString = ''; foreach ($headers_array as $value) { $headerString .= $value->getName() . ': ' . $value . " "; } $log_message = '{code_status} ({code}) Request Details:[ {r_method} {r_resource} {r_scheme} {r_headers} ]'; $httpScheme = strtoupper(str_replace('https', 'http', $request->getScheme())) . $request->getProtocolVersion(); $log_params = array('code' => $e->getErrorNo(), 'code_status' => $e->getError(), 'r_method' => $request->getUrl(), 'r_resource' => $request->getRawHeaders(), 'r_scheme' => $httpScheme, 'r_headers' => $headerString); self::$logger->emergency($log_message, $log_params); throw $exception; } $this->responseCode = $response->getStatusCode(); $this->responseText = trim($response->getBody(true)); $this->responseLength = $response->getContentLength(); $this->responseMimeType = $response->getContentType(); $this->responseObj = array(); $content_type = $response->getContentType(); $firstChar = substr($this->responseText, 0, 1); if (strpos($content_type, '/json') !== false && ($firstChar == '{' || $firstChar == '[')) { $response_obj = @json_decode($this->responseText, true); if (is_array($response_obj)) { $this->responseObj = $response_obj; } } $status = self::getStatusMessage($this->responseCode); $code_class = floor($this->responseCode / 100); DebugData::$raw = $this->responseText; DebugData::$opts = array('request_headers' => $request_headers, 'response_headers' => $response->getRawHeaders()); if ($request instanceof \Guzzle\Http\Message\EntityEnclosingRequestInterface) { DebugData::$opts['request_body'] = (string) $request->getBody(); } DebugData::$opts['request_type'] = class_implements($request); DebugData::$data = $this->responseObj; DebugData::$code = $this->responseCode; DebugData::$code_status = $status; DebugData::$code_class = $code_class; DebugData::$exception = null; DebugData::$time_elapsed = microtime(true) - $start; if ($code_class != 2) { $uri = $request->getUrl(); if (!empty($this->responseCode) && isset($this->responseObj['message'])) { $message = 'Code: ' . $this->responseCode . '; Message: ' . $this->responseObj['message']; } else { $message = 'API returned HTTP code of ' . $this->responseCode . ' when fetching from ' . $uri; } DebugData::$exception = $message; $this->debugCallback(DebugData::toArray()); self::$logger->error($this->responseText); // Create better status to show up in logs $status .= ': ' . $request->getMethod() . ' ' . $uri; if ($request instanceof \Guzzle\Http\Message\EntityEnclosingRequestInterface) { $body = $request->getBody(); if ($body instanceof \Guzzle\Http\EntityBodyInterface) { $status .= ' with Content-Length of ' . $body->getContentLength() . ' and Content-Type of ' . $body->getContentType(); } } $exception = new ResponseException($status, $this->responseCode, $uri, DebugData::$opts, $this->responseText); $exception->requestObj = $request; $exception->responseObj = $response; throw $exception; } $this->debugCallback(DebugData::toArray()); }
/** * Returns debug data from the last API call in a backwards-compatible way. * * @return array */ public function getDebugData() { return \Apigee\Util\DebugData::toArray(); }