private static <T extends Trait> Map<CorsHeader, String> deduceCorsHeaders(
            Context<T> context,
            String path,
            PathItem pathItem,
            CorsTrait corsTrait
    ) {
        Map<CorsHeader, String> corsHeaders = new HashMap<>();
        corsHeaders.put(CorsHeader.MAX_AGE, String.valueOf(corsTrait.getMaxAge()));
        corsHeaders.put(CorsHeader.ALLOW_ORIGIN, corsTrait.getOrigin());
        corsHeaders.put(CorsHeader.ALLOW_METHODS, getAllowMethods(pathItem));

        if (context.usesHttpCredentials()) {
            corsHeaders.put(CorsHeader.ALLOW_CREDENTIALS, "true");
        }

        // Find each header defined in this PathItem. The collected headers are added to the
        // Access-Control-Allow-Headers header list. Note that any further modifications that
        // add headers during the Smithy to OpenAPI conversion process will need to update this
        // list of headers accordingly.
        Set<String> headerNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        headerNames.addAll(corsTrait.getAdditionalAllowedHeaders());

        // Sets additional allowed headers from the API Gateway config.
        Set<String> additionalAllowedHeaders = context.getConfig()
                .getExtensions(ApiGatewayConfig.class)
                .getAdditionalAllowedCorsHeadersSet();
        headerNames.addAll(additionalAllowedHeaders);
        headerNames.addAll(findAllHeaders(path, pathItem));

        // Add all headers generated by security schemes.
        for (SecuritySchemeConverter<? extends Trait> converter : context.getSecuritySchemeConverters()) {
            headerNames.addAll(getSecuritySchemeRequestHeaders(context, converter));
        }

        // Add protocol headers.
        Model model = context.getModel();
        TopDownIndex topDownIndex = TopDownIndex.of(model);
        Map<String, OperationShape> operations = topDownIndex.getContainedOperations(context.getService())
                .stream()
                .collect(Collectors.toMap(o -> o.getId().getName(), o -> o));
        for (OperationObject operationObject : pathItem.getOperations().values()) {
            if (operationObject.getOperationId().isPresent()) {
                OperationShape operationShape = operations.get(operationObject.getOperationId().get());
                headerNames.addAll(context.getOpenApiProtocol().getProtocolRequestHeaders(context, operationShape));
            }
        }

        LOGGER.fine(() -> String.format(
                "Adding the following %s headers to `%s`: %s",
                CorsHeader.ALLOW_HEADERS,
                path,
                headerNames));
        corsHeaders.put(CorsHeader.ALLOW_HEADERS, String.join(",", headerNames));

        return corsHeaders;
    }
Adds CORS-preflight OPTIONS requests using mock API Gateway integrations.

<p>This allows clients to first make an OPTIONS request to a URI to
determine what possible actions can be made on the URI. Rather than require
models to explicitly define and implement these protocol-specific
integrations, we can generate a static response using API Gateway mock
integrations.

<p>TODO: Only add security scheme headers on a per/operation basis.
We currently add security headers to the CORS headers that contains all
security schemes defined in the model. An improvement here would be to only
include headers that are added by security schemes on a per/operation basis.

<p>This extension only takes effect if the service being converted to
OpenAPI has the CORS trait.

@see <a href="https://fetch.spec.whatwg.org/#cors-preflight-fetch-0">CORS-preflight fetch</a>
smithy-aws-apigateway-openapi/src/main/java/software/amazon/smithy/aws/apigateway/openapi/AddCorsPreflightIntegration.java