* @since 1.0.0 */ abstract class HttpServicePresenter extends Presenter { protected IResponse $response; protected IRequest $request; protected Serializer $serializer; public function injectResponse(IResponse $response) : void { $this->response = $response; } public function injectRequest(IRequest $request) : void { $this->request = $request; } public function injectSerializer(Serializer $serializer) : void { $this->serializer = $serializer; } /** * Set some basic CORS headers and proper configuration of OPTIONS methods. Then authenticate each request. */ protected function startup() { parent::startup(); $this->response->setContentType('application/json', 'utf-8'); $this->response->setHeader('Access-Control-Allow-Origin', '*'); $this->response->setHeader('Access-Control-Expose-Headers', 'id'); if($this->request->method == 'OPTIONS') { $this->response->setHeader('Access-Control-Allow-Methods', 'POST, PUT, GET, DELETE'); $this->response->setHeader( 'Access-Control-Allow-Headers', 'origin, content-type, accept, X-API-Key'); $this->response->setCode(IResponse::S200_OK); $this->terminate(); } } /** * Returns OpenAPI specification in yml format */ public function actionOpenapi() { $spec = @$this->getContext()->getParameters()['docDir'] . "/openapi.yml"; $this->sendResponse(new \Nette\Application\Responses\FileResponse($spec, 'openapi.yml', 'application/x-yaml')); } protected function sendValidationErrorResponse($message = null, $code = IResponse::S400_BAD_REQUEST) { $this->response->setCode($code); $this->sendResponse(new TextResponse($this->ensureJsonAsString($message))); $this->terminate(); } protected function sendExceptionErrorResponse(Throwable $exception, $code = IResponse::S500_INTERNAL_SERVER_ERROR) { $this->response->setCode(IResponse::S500_INTERNAL_SERVER_ERROR); $this->sendResponse(new JsonResponse(['fault' => [ 'faultcode' => $code, 'faultstring' => $exception->getMessage(), 'detail' => get_class($exception) . ": " . $exception->getMessage() ]])); $this->terminate(); } protected function sendJsonResponse($json, $code = IResponse::S200_OK) { $this->response->setCode($code); $this->sendResponse(new TextResponse($this->ensureJsonAsString($json))); $this->terminate(); } protected function sendCreatedResponse($json = null, $code = IResponse::S201_CREATED) { $this->sendResponseWithCodeAndOptionalJson($code, $json); } protected function sendAcceptedResponse($json = null, $code = IResponse::S202_ACCEPTED) { $this->sendResponseWithCodeAndOptionalJson($code, $json); } protected function sendNotFoundResponse($json = null, $code = IResponse::S404_NOT_FOUND) { $this->sendResponseWithCodeAndOptionalJson($code, $json); } protected function sendResponseWithCodeAndOptionalJson(int $code, $json = null) { $this->response->setCode($code); if ($json) { $this->sendResponse(new TextResponse($this->ensureJsonAsString($json))); } $this->terminate(); } protected function parseJsonPayload(bool $exception_on_failure = false, bool $as_array = true) : array { $payload = json_decode(file_get_contents('php://input'), $as_array); if (!$payload) { if ($exception_on_failure) { throw new \RuntimeException("No valid json to deserialize in request body"); } else { $this->sendValidationErrorResponse("Malformed JSON body"); } } return $payload; } protected function ensureJsonAsString($json) : string { if (is_array($json)) { $json = json_encode($json); } elseif (is_object($json)) { $json = $this->serializer->serialize($json, 'json'); } return $json; } }