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

Code before:
        case unexpctedResponseStatus(HTTPStatus, uri: URI)
        case badJSON(Error)
    }

    internal var cached: T?
    internal var request: EventLoopFuture<T>?
    internal var headers: HTTPHeaders?
    internal var cacheUntil: Date?

    private let sync: Lock
    private let uri: URI

    /// The designated initializer.
    /// - Parameters:
    ///   - uri: The `URI` of the resource to be downloaded.
    public init(uri: URI) {
        self.uri = uri
        self.sync = .init()
    }

    /// Downloads the resource.
    /// - Parameters:
    ///   - request: The `Request` which is initiating the download.
    ///   - logger: An optional logger
    public func get(on request: Request, logger: Logger? = nil) -> EventLoopFuture<T> {
        return self.download(on: request.eventLoop, using: request.client, logger: logger)
    }

    /// Downloads the resource.
    /// - Parameters:
    ///   - eventLoop: The `EventLoop` to use for the download.
    ///   - 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)
        }


Review comment (suggestion):
This should pass `logger ?? request.logger` so that we use the request's logger by default. 

Code after:

/// Handles the complexities of HTTP caching.
public final class EndpointCache<T> where T: Decodable {
    private var cached: T?
    private var request: EventLoopFuture<T>?
    private var headers: HTTPHeaders?
    private var cacheUntil: Date?

    private let sync: Lock
    private let uri: URI

    /// The designated initializer.
    /// - Parameters:
    ///   - uri: The `URI` of the resource to be downloaded.
    public init(uri: URI) {
        self.uri = uri
        self.sync = .init()
    }

    /// Downloads the resource.
    /// - Parameters:
    ///   - request: The `Request` which is initiating the download.
    ///   - logger: An optional logger
    public func get(on request: Request, logger: Logger? = nil) -> EventLoopFuture<T> {
        return self.download(on: request.eventLoop, using: request.client, logger: logger ?? request.logger)
    }

    /// Downloads the resource.
    /// - Parameters:
    ///   - eventLoop: The `EventLoop` to use for the download.
    ///   - client: The `Client` which will perform the download.
    ///   - 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)")