Repository: vapor/vapor
File: Sources/Vapor/HTTP/EndpointCache.swift (Swift)

Code before:
    ///   - client: The `Client` which will perform the download.
    ///   - logger: An optional logger
    public func get(on eventLoop: EventLoop, using client: Client, logger: Logger?) -> EventLoopFuture<T> {
        self.sync.lock()
        defer { self.sync.unlock() }

        if let cached = self.cached, let cacheUntil = self.cacheUntil, Date() < cacheUntil {
            // If no-cache was set on the header, you *always* have to validate with the server.
            // must-revalidate does not require checking with the server until after it expires.
            if self.headers == nil || self.headers?.cacheControl == nil || self.headers?.cacheControl?.noCache == false {
                return eventLoop.makeSucceededFuture(cached)
            }
        }

        // Don't make a new request if one is already running.
        if let request = self.request {
            // The current request may be happening on a different event loop.
            return request.hop(to: eventLoop)
        }

        logger?.debug("Requesting data from \(self.uri)")

        self.request = self.download(on: eventLoop, using: client, logger: logger)

        // Once the request finishes, clear the current request and return the data.
        return self.request!.map { data in
            // Synchronize access to shared state
            self.sync.lock()
            defer { self.sync.unlock() }
            self.request = nil

            return data
        }
    }

    internal func download(on eventLoop: EventLoop, using client: Client, logger: Logger?) -> EventLoopFuture<T> {
        // https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4
        var headers: HTTPHeaders = [:]
        if let eTag = self.headers?.firstValue(name: .eTag) {
            headers.add(name: .ifNoneMatch, value: eTag)
        }

        if let lastModified = self.headers?.lastModified {
            // TODO: If using HTTP/1.0 then this should be .ifUnmodifiedSince instead. Don't know
            // how to determine that right now.
            headers.add(name: .ifModifiedSince, value: lastModified.serialize())
        }

        // Cache-Control max-age is calculated against the request date.
        let requestSentAt = Date()


Review comment (bug):
Nit, doing this is preferred:
```swift
let request = self.download(on: eventLoop, using: client, logger: logger)
self.request = request
return request.map { ... }
```
IUOs can create bugs if / when the code is refactored at a later date.

Code after:
    ///   - logger: An optional logger
    public func get(using client: Client, logger: Logger? = nil, on eventLoop: EventLoop) -> EventLoopFuture<T> {
        self.sync.lock()
        defer { self.sync.unlock() }

        if let cached = self.cached, let cacheUntil = self.cacheUntil, Date() < cacheUntil {
            // If no-cache was set on the header, you *always* have to validate with the server.
            // must-revalidate does not require checking with the server until after it expires.
            if self.headers == nil || self.headers?.cacheControl == nil || self.headers?.cacheControl?.noCache == false {
                return eventLoop.makeSucceededFuture(cached)
            }
        }

        // Don't make a new request if one is already running.
        if let request = self.request {
            // The current request may be happening on a different event loop.
            return request.hop(to: eventLoop)
        }

        logger?.debug("Requesting data from \(self.uri)")

        let request = self.download(on: eventLoop, using: client, logger: logger)
        self.request = request

        // Once the request finishes, clear the current request and return the data.
        return request.map { data in
            // Synchronize access to shared state
            self.sync.lock()
            defer { self.sync.unlock() }
            self.request = nil

            return data
        }
    }

    private func download(on eventLoop: EventLoop, using client: Client, logger: Logger?) -> EventLoopFuture<T> {
        // https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4
        var headers: HTTPHeaders = [:]
        if let eTag = self.headers?.firstValue(name: .eTag) {
            headers.add(name: .ifNoneMatch, value: eTag)
        }

        if let lastModified = self.headers?.lastModified {
            // TODO: If using HTTP/1.0 then this should be .ifUnmodifiedSince instead. Don't know
            // how to determine that right now.
            headers.add(name: .ifModifiedSince, value: lastModified.serialize())
        }

        // Cache-Control max-age is calculated against the request date.
        let requestSentAt = Date()