From 15303125f6cc3411283509064cca91203dc9886f Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 16 Aug 2024 01:57:50 +0200 Subject: [PATCH] Support CORS preflight requests when the storage request api returns an error (#878) * Add CORS headers when the REST API is returning an error * Use the allowedOrigin instead of the wilcard when setting the origin Signed-off-by: Arnaud --------- Signed-off-by: Arnaud --- codex/rest/api.nim | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/codex/rest/api.nim b/codex/rest/api.nim index b209e7c9..8197d8d4 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -418,6 +418,8 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) = return RestApiResponse.error(Http500) proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = + let allowedOrigin = router.allowedOrigin + router.rawApi( MethodPost, "/api/codex/v1/storage/request/{cid}") do (cid: Cid) -> RestApiResponse: @@ -432,37 +434,44 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = ## tolerance - allowed number of nodes that can be lost before content is lost ## colateral - requested collateral from hosts when they fill slot + var headers = newSeq[(string,string)]() + + if corsOrigin =? allowedOrigin: + headers.add(("Access-Control-Allow-Origin", corsOrigin)) + headers.add(("Access-Control-Allow-Methods", "POST, OPTIONS")) + headers.add(("Access-Control-Max-Age", "86400")) + try: without contracts =? node.contracts.client: - return RestApiResponse.error(Http503, "Purchasing unavailable") + return RestApiResponse.error(Http503, "Purchasing unavailable", headers = headers) without cid =? cid.tryGet.catch, error: - return RestApiResponse.error(Http400, error.msg) + return RestApiResponse.error(Http400, error.msg, headers = headers) let body = await request.getBody() without params =? StorageRequestParams.fromJson(body), error: - return RestApiResponse.error(Http400, error.msg) + return RestApiResponse.error(Http400, error.msg, headers = headers) let nodes = params.nodes |? 1 let tolerance = params.tolerance |? 0 # prevent underflow if tolerance > nodes: - return RestApiResponse.error(Http400, "Invalid parameters: `tolerance` cannot be greater than `nodes`") + return RestApiResponse.error(Http400, "Invalid parameters: `tolerance` cannot be greater than `nodes`", headers = headers) let ecK = nodes - tolerance let ecM = tolerance # for readability # ensure leopard constrainst of 1 < K ≥ M if ecK <= 1 or ecK < ecM: - return RestApiResponse.error(Http400, "Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`") + return RestApiResponse.error(Http400, "Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`", headers = headers) without expiry =? params.expiry: - return RestApiResponse.error(Http400, "Expiry required") + return RestApiResponse.error(Http400, "Expiry required", headers = headers) if expiry <= 0 or expiry >= params.duration: - return RestApiResponse.error(Http400, "Expiry needs value bigger then zero and smaller then the request's duration") + return RestApiResponse.error(Http400, "Expiry needs value bigger then zero and smaller then the request's duration", headers = headers) without purchaseId =? await node.requestStorage( cid, @@ -477,14 +486,14 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = if error of InsufficientBlocksError: return RestApiResponse.error(Http400, "Dataset too small for erasure parameters, need at least " & - $(ref InsufficientBlocksError)(error).minSize.int & " bytes") + $(ref InsufficientBlocksError)(error).minSize.int & " bytes", headers = headers) - return RestApiResponse.error(Http500, error.msg) + return RestApiResponse.error(Http500, error.msg, headers = headers) return RestApiResponse.response(purchaseId.toHex) except CatchableError as exc: trace "Excepting processing request", exc = exc.msg - return RestApiResponse.error(Http500) + return RestApiResponse.error(Http500, headers = headers) router.api( MethodGet,