/** * @param Envelope $envelope * @param Queue $queue * @return DeliveryResult */ protected function handleDelivery(Envelope $envelope, Queue $queue) : DeliveryResult { $this->countMessagesConsumed++; $this->countMessagesUnacked++; $this->lastDeliveryTag = $envelope->getDeliveryTag(); $this->timestampLastMessage = microtime(true); $this->ack(); $this->logger->debug('Handling delivery of message', $this->extractMessageInformation($envelope)); if ($envelope->getAppId() === 'Humus\\Amqp') { $this->handleInternalMessage($envelope); return DeliveryResult::MSG_ACK(); } try { $request = $this->requestFromEnvelope($envelope); $callback = $this->deliveryCallback; $response = $callback($request); if ('' === $request->id()) { // notifications have no reply return DeliveryResult::MSG_ACK(); } if (!$response instanceof JsonRpcResponse) { $response = JsonRpcResponse::withResult($envelope->getCorrelationId(), $response); } } catch (Exception\InvalidJsonRpcVersion $e) { $this->logger->error('Invalid json rpc version', $this->extractMessageInformation($envelope)); $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32600)); } catch (Exception\InvalidJsonRpcRequest $e) { $this->logger->error('Invalid json rpc request', $this->extractMessageInformation($envelope)); $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32600)); } catch (Exception\JsonParseError $e) { $this->logger->error('Json parse error', $this->extractMessageInformation($envelope)); $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32700)); } catch (\Throwable $e) { $extra = $this->extractMessageInformation($envelope); $extra['exception_class'] = get_class($e); $extra['exception_message'] = $e->getMessage(); $extra['exception_trace'] = $e->getTraceAsString(); $this->logger->error('Exception occurred', $extra); $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32603)); } $this->sendReply($response, $envelope); return DeliveryResult::MSG_ACK(); }
/** * @param Envelope $envelope * @return Response */ private function responseFromEnvelope(Envelope $envelope) : Response { if ($envelope->getHeader('jsonrpc') !== JsonRpcResponse::JSONRPC_VERSION || $envelope->getContentEncoding() !== 'UTF-8' || $envelope->getContentType() !== 'application/json') { return JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32603, 'Invalid JSON-RPC response')); } $payload = json_decode($envelope->getBody(), true); if (!in_array($envelope->getCorrelationId(), $this->requestIds)) { $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32603, 'Mismatched JSON-RPC IDs')); } elseif (isset($payload['result'])) { $response = JsonRpcResponse::withResult($envelope->getCorrelationId(), $payload['result']); } elseif (!isset($payload['error']['code']) || !isset($payload['error']['message']) || !is_int($payload['error']['code']) || !is_string($payload['error']['message'])) { $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32603, 'Invalid JSON-RPC response')); } else { $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError($payload['error']['code'], $payload['error']['message']), $payload['data'] ?? null); } return $response; }