Repository: vapor/vapor
File: Sources/Vapor/Middleware/CORSMiddleware.swift (Swift)

Code before:
        // If it is, create empty response otherwise get response from the responder chain.
        let response = request.isPreflight
            ? request.eventLoop.makeSucceededFuture(.init())
            : next.respond(to: request)
        
        return response.map { response in
            // Modify response headers based on CORS settings
            let originBasedAccessControlAllowHeader = self.configuration.allowedOrigin.header(forRequest: request)
            response.headers.replaceOrAdd(name: .accessControlAllowOrigin, value: originBasedAccessControlAllowHeader)
            response.headers.replaceOrAdd(name: .accessControlAllowHeaders, value: self.configuration.allowedHeaders)
            response.headers.replaceOrAdd(name: .accessControlAllowMethods, value: self.configuration.allowedMethods)
            
            if let exposedHeaders = self.configuration.exposedHeaders {
                response.headers.replaceOrAdd(name: .accessControlExpose, value: exposedHeaders)
            }
            
            if let cacheExpiration = self.configuration.cacheExpiration {
                response.headers.replaceOrAdd(name: .accessControlMaxAge, value: String(cacheExpiration))
            }
            
            if self.configuration.allowCredentials {
                response.headers.replaceOrAdd(name: .accessControlAllowCredentials, value: "true")
            }

            if case .originBased = self.configuration.allowedOrigin, !originBasedAccessControlAllowHeader.isEmpty {
                response.headers.add(name: "vary", value: "origin")
            }
            
            return response
        }
    }
}

// MARK: Private

private extension Request {
    /// Returns `true` if the request is a pre-flight CORS request.
    var isPreflight: Bool {
        return self.method == .OPTIONS && self.headers[.accessControlRequestMethod].first != nil
    }
}



Review comment (suggestion):
`HTTPHeaders.Name.vary` should be available here.
```suggestion
                response.headers.add(name: .vary, value: "origin")
```

Code after:
        // If it is, create empty response otherwise get response from the responder chain.
        let response = request.isPreflight
            ? request.eventLoop.makeSucceededFuture(.init())
            : next.respond(to: request)
        
        return response.map { response in
            // Modify response headers based on CORS settings
            let originBasedAccessControlAllowHeader = self.configuration.allowedOrigin.header(forRequest: request)
            response.headers.replaceOrAdd(name: .accessControlAllowOrigin, value: originBasedAccessControlAllowHeader)
            response.headers.replaceOrAdd(name: .accessControlAllowHeaders, value: self.configuration.allowedHeaders)
            response.headers.replaceOrAdd(name: .accessControlAllowMethods, value: self.configuration.allowedMethods)
            
            if let exposedHeaders = self.configuration.exposedHeaders {
                response.headers.replaceOrAdd(name: .accessControlExpose, value: exposedHeaders)
            }
            
            if let cacheExpiration = self.configuration.cacheExpiration {
                response.headers.replaceOrAdd(name: .accessControlMaxAge, value: String(cacheExpiration))
            }
            
            if self.configuration.allowCredentials {
                response.headers.replaceOrAdd(name: .accessControlAllowCredentials, value: "true")
            }

            if case .originBased = self.configuration.allowedOrigin, !originBasedAccessControlAllowHeader.isEmpty {
                response.headers.add(name: .vary, value: "origin")
            }
            
            return response
        }
    }
}

// MARK: Private

private extension Request {
    /// Returns `true` if the request is a pre-flight CORS request.
    var isPreflight: Bool {
        return self.method == .OPTIONS && self.headers[.accessControlRequestMethod].first != nil
    }
}