public createOptionsHandlerMiddleware()

in src/blob/middlewares/PreflightMiddlewareFactory.ts [28:141]


  public createOptionsHandlerMiddleware(
    metadataStore: IBlobMetadataStore
  ): ErrorRequestHandler {
    return (
      err: MiddlewareError | Error,
      req: Request,
      res: Response,
      next: NextFunction
    ) => {
      if (req.method.toUpperCase() === MethodConstants.OPTIONS) {
        const context = new BlobStorageContext(
          res.locals,
          DEFAULT_CONTEXT_PATH
        );

        const requestId = context.contextId;
        const account = context.account!;

        this.logger.info(
          `PreflightMiddlewareFactory.createOptionsHandlerMiddleware(): OPTIONS request.`,
          requestId
        );

        const origin = req.header(HeaderConstants.ORIGIN);
        if (origin === undefined || typeof origin !== "string") {
          return next(
            StorageErrorFactory.getInvalidCorsHeaderValue(requestId, {
              MessageDetails: `Invalid required CORS header Origin ${JSON.stringify(
                origin
              )}`
            })
          );
        }

        const requestMethod = req.header(
          HeaderConstants.ACCESS_CONTROL_REQUEST_METHOD
        );
        if (requestMethod === undefined || typeof requestMethod !== "string") {
          return next(
            StorageErrorFactory.getInvalidCorsHeaderValue(requestId, {
              MessageDetails: `Invalid required CORS header Access-Control-Request-Method ${JSON.stringify(
                requestMethod
              )}`
            })
          );
        }

        const requestHeaders = req.headers[
          HeaderConstants.ACCESS_CONTROL_REQUEST_HEADERS
        ] as string;

        metadataStore
          .getServiceProperties(context, account)
          .then((properties) => {
            if (properties === undefined || properties.cors === undefined) {
              return next(
                StorageErrorFactory.corsPreflightFailure(requestId, {
                  MessageDetails: "No CORS rules matches this request"
                })
              );
            }

            const corsSet = properties.cors;
            for (const cors of corsSet) {
              if (
                !this.checkOrigin(origin, cors.allowedOrigins) ||
                !this.checkMethod(requestMethod, cors.allowedMethods)
              ) {
                continue;
              }
              if (
                requestHeaders !== undefined &&
                !this.checkHeaders(requestHeaders, cors.allowedHeaders || "")
              ) {
                continue;
              }

              res.setHeader(
                HeaderConstants.ACCESS_CONTROL_ALLOW_ORIGIN,
                origin
              );
              res.setHeader(
                HeaderConstants.ACCESS_CONTROL_ALLOW_METHODS,
                requestMethod
              );
              if (requestHeaders !== undefined) {
                res.setHeader(
                  HeaderConstants.ACCESS_CONTROL_ALLOW_HEADERS,
                  requestHeaders
                );
              }
              res.setHeader(
                HeaderConstants.ACCESS_CONTROL_MAX_AGE,
                cors.maxAgeInSeconds
              );
              res.setHeader(
                HeaderConstants.ACCESS_CONTROL_ALLOW_CREDENTIALS,
                "true"
              );

              return next();
            }
            return next(
              StorageErrorFactory.corsPreflightFailure(requestId, {
                MessageDetails: "No CORS rules matches this request"
              })
            );
          })
          .catch(next);
      } else {
        next(err);
      }
    };
  }