Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let swiftSettings: [SwiftSetting] = [

let package = Package(
name: "hummingbird",
platforms: [.macOS(.v14), .iOS(.v17), .macCatalyst(.v17), .tvOS(.v17), .visionOS(.v1)],
platforms: [.macOS(.v14), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v17), .visionOS(.v1)],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
platforms: [.macOS(.v14), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v17), .visionOS(.v1)],
platforms: [.macOS(.v10_15), .iOS(.v13), .macCatalyst(.v13), .tvOS(.v13), .visionOS(.v1)],

products: [
.library(name: "Hummingbird", targets: ["Hummingbird"]),
.library(name: "HummingbirdCore", targets: ["HummingbirdCore"]),
Expand Down
2 changes: 1 addition & 1 deletion Package@swift-6.0.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let swiftSettings: [SwiftSetting] = [

let package = Package(
name: "hummingbird",
platforms: [.macOS(.v14), .iOS(.v17), .macCatalyst(.v17), .tvOS(.v17), .visionOS(.v1)],
platforms: [.macOS(.v14), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v17), .visionOS(.v1)],
products: [
.library(name: "Hummingbird", targets: ["Hummingbird"]),
.library(name: "HummingbirdCore", targets: ["HummingbirdCore"]),
Expand Down
2 changes: 1 addition & 1 deletion Package@swift-6.1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let swiftSettings: [SwiftSetting] = [

let package = Package(
name: "hummingbird",
platforms: [.macOS(.v14), .iOS(.v17), .macCatalyst(.v17), .tvOS(.v17), .visionOS(.v1)],
platforms: [.macOS(.v14), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v17), .visionOS(.v1)],
products: [
.library(name: "Hummingbird", targets: ["Hummingbird"]),
.library(name: "HummingbirdCore", targets: ["HummingbirdCore"]),
Expand Down
6 changes: 6 additions & 0 deletions Sources/Hummingbird/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ extension ApplicationProtocol {
extension ApplicationProtocol {
/// Construct application and run it
public func run() async throws {
// `#available()` logic must be placed within this method as Service
// protocol requires `run()` method is available from iOS 13+
guard #available(iOS 17.0, *) else {
return
}

let dateCache = DateCache()
let responder = try await self.responder

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// SPDX-License-Identifier: Apache-2.0
//

@available(iOS 16, *)
extension URLEncodedFormEncoder: ResponseEncoder {
/// Extend URLEncodedFormEncoder to support generating a ``HummingbirdCore/Response``. Sets body and header values
/// - Parameters:
Expand All @@ -26,6 +27,7 @@ extension URLEncodedFormEncoder: ResponseEncoder {
}
}

@available(iOS 16, *)
extension URLEncodedFormDecoder: RequestDecoder {
/// Extend URLEncodedFormDecoder to decode from ``HummingbirdCore/Request``.
/// - Parameters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import Foundation

/// The wrapper struct for decoding URL encoded form data to Codable classes
@available(iOS 16, *)
public struct URLEncodedFormDecoder: Sendable {
/// The strategy to use for decoding `Date` values.
public enum DateDecodingStrategy: Sendable {
Expand Down Expand Up @@ -75,6 +76,7 @@ public struct URLEncodedFormDecoder: Sendable {
}
}

@available(iOS 16, *)
private class _URLEncodedFormDecoder: Decoder {
// MARK: Properties

Expand Down Expand Up @@ -421,6 +423,7 @@ private class _URLEncodedFormDecoder: Decoder {
}
}

@available(iOS 16, *)
extension _URLEncodedFormDecoder: SingleValueDecodingContainer {
func decodeNil() -> Bool {
(try? self.unboxNil(self.storage.topContainer)) ?? false
Expand Down Expand Up @@ -487,6 +490,7 @@ extension _URLEncodedFormDecoder: SingleValueDecodingContainer {
}
}

@available(iOS 16, *)
extension _URLEncodedFormDecoder {
func unboxNil(_ node: URLEncodedFormNode) throws -> Bool {
switch node {
Expand Down Expand Up @@ -686,6 +690,7 @@ extension _URLEncodedFormDecoder {
}
}

@available(iOS 16, *)
private struct URLEncodedFormDecodingStorage {
/// the container stack
private var containers: [URLEncodedFormNode] = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import Foundation

/// The wrapper struct for encoding Codable classes to URL encoded form data
@available(iOS 16, *)
public struct URLEncodedFormEncoder: Sendable {
/// The strategy to use for encoding `Date` values.
public enum DateEncodingStrategy: Sendable {
Expand Down Expand Up @@ -80,6 +81,7 @@ public struct URLEncodedFormEncoder: Sendable {
}

/// Internal QueryEncoder class. Does all the heavy lifting
@available(iOS 16, *)
private class _URLEncodedFormEncoder: Encoder {
var codingPath: [any CodingKey]

Expand Down Expand Up @@ -273,6 +275,7 @@ private class _URLEncodedFormEncoder: Encoder {
}
}

@available(iOS 16, *)
extension _URLEncodedFormEncoder: SingleValueEncodingContainer {
func encodeResult(_ value: URLEncodedFormNode) {
self.storage.push(container: value)
Expand Down Expand Up @@ -310,6 +313,7 @@ extension _URLEncodedFormEncoder: SingleValueEncodingContainer {
}
}

@available(iOS 16, *)
extension _URLEncodedFormEncoder {
func box(_ date: Date) throws -> URLEncodedFormNode {
switch self.options.dateEncodingStrategy {
Expand Down Expand Up @@ -355,6 +359,7 @@ extension _URLEncodedFormEncoder {
}

/// storage for Query Encoder. Stores a stack of QueryEncoder containers, plus leaf objects
@available(iOS 16, *)
private struct URLEncodedFormEncoderStorage {
/// the container stack
private var containers: [URLEncodedFormNode] = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ extension URLEncodedFormError {
}
}
/// Internal representation of URL encoded form data used by both encode and decode
@available(iOS 16, *)
enum URLEncodedFormNode: CustomStringConvertible, Equatable {
/// holds a value
case leaf(NodeValue?)
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/HTTP/Cookie.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public import Foundation
#endif

/// Structure holding a single cookie
@available(iOS 16, *)
public struct Cookie: Sendable, CustomStringConvertible {
public struct ValidationError: Error {
enum Reason {
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/HTTP/Cookies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/// Structure holding an array of cookies
///
/// Cookies can be accessed from request via `Request.cookies`.
@available(iOS 16, *)
public struct Cookies: Sendable {
/// Construct cookies accessor from `Request`
/// - Parameter request: request to get cookies from
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/HTTP/Request+Cookies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

public import HummingbirdCore

@available(iOS 16, *)
extension Request {
/// access cookies from request. When accessing this for the first time the Cookies struct will be created
public var cookies: Cookies {
Expand Down
2 changes: 2 additions & 0 deletions Sources/Hummingbird/HTTP/Response+Cookies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@

public import HummingbirdCore

@available(iOS 16, *)
extension Response {
/// Set cookie on response
public mutating func setCookie(_ cookie: Cookie) {
self.headers[values: .setCookie].append(cookie.description)
}
}

@available(iOS 16, *)
extension EditedResponse {
/// Set cookie on reponse patch
///
Expand Down
2 changes: 2 additions & 0 deletions Sources/Hummingbird/Middleware/FileMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public protocol FileMiddlewareFileAttributes {
/// "if-modified-since", "if-none-match", "if-range" and 'range" headers. It will output "content-length",
/// "modified-date", "eTag", "content-type", "cache-control" and "content-range" headers where
/// they are relevant.
@available(iOS 16, *)
public struct FileMiddleware<Context: RequestContext, Provider: FileProvider>: RouterMiddleware
where Provider.FileAttributes: FileMiddlewareFileAttributes {
let cacheControl: CacheControl
Expand Down Expand Up @@ -221,6 +222,7 @@ where Provider.FileAttributes: FileMiddlewareFileAttributes {
}
}

@available(iOS 16, *)
extension FileMiddleware {
/// Whether to return data from the file or a not modified response
private enum FileResult {
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Middleware/MiddlewareGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

/// Group of middleware that can be used to create a responder chain. Each middleware calls the next one
@available(iOS 16, *)
public final class MiddlewareGroup<Context> {
var middlewares: [any MiddlewareProtocol<Request, Response, Context>]

Expand Down
2 changes: 2 additions & 0 deletions Sources/Hummingbird/Middleware/TracingMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import Foundation
/// Swift-Distributed-Tracing has a flexible backend, which will need to be initialized before any traces are recorded.
///
/// A list of implementations is available in the swift-distributed-tracing repository's README.
@available(iOS 16, *)
public struct TracingMiddleware<Context: RequestContext>: RouterMiddleware {
private let headerNamesToRecord: Set<RecordingHeader>
private let queryParametersToRedact: Set<Substring>
Expand Down Expand Up @@ -196,6 +197,7 @@ public protocol RemoteAddressRequestContext: RequestContext {
var remoteAddress: SocketAddress? { get }
}

@available(iOS 16, *)
struct RecordingHeader: Hashable {
let name: HTTPField.Name
let attributeName: String
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/EndpointResponder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import HTTPTypes

/// Stores endpoint responders for each HTTP method
@available(iOS 16, *)
@usableFromInline
struct EndpointResponders<Context>: Sendable {
init(path: RouterPath) {
Expand Down
2 changes: 2 additions & 0 deletions Sources/Hummingbird/Router/RouteCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import HTTPTypes

/// Collection of routes
@available(iOS 16, *)
public final class RouteCollection<Context: RequestContext>: RouterMethods {
/// Initialize RouteCollection
public init(context: Context.Type = BasicRequestContext.self) {
Expand Down Expand Up @@ -52,6 +53,7 @@ public final class RouteCollection<Context: RequestContext>: RouterMethods {
let middlewares: MiddlewareGroup<Context>
}

@available(iOS 16, *)
extension RouterMethods {
/// Add route collection to router
/// - Parameters
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/Router+validation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import FoundationEssentials
import Foundation
#endif

@available(iOS 16, *)
extension Router {
/// Route description
public struct RouteDescription: CustomStringConvertible {
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public import HummingbirdCore
/// Both of these match routes which start with "/user" and the next path segment being anything.
/// The second version extracts the path segment out and adds it to `Request.parameters` with the
/// key "id".
@available(iOS 16, *)
public final class Router<Context: RequestContext>: RouterMethods, HTTPResponderBuilder {
var trie: RouterPathTrieBuilder<EndpointResponders<Context>>
public let middlewares: MiddlewareGroup<Context>
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/RouterGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public import HummingbirdCore
/// .put(":id", use: todoController.update)
/// .delete(":id", use: todoController.delete)
/// ```
@available(iOS 16, *)
public struct RouterGroup<Context: RequestContext>: RouterMethods {
let path: RouterPath
let parent: any RouterMethods<Context>
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/RouterMethods.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public protocol RouterMethods<Context>: _HB_SendableMetatype {
func add(middleware: any MiddlewareProtocol<Request, Response, Context>) -> Self
}

@available(iOS 16, *)
extension RouterMethods {
/// Add path for async closure
@discardableResult public func on(
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Router/RouterResponder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import NIOCore

@available(iOS 16, *)
public struct RouterResponder<Context: RequestContext>: HTTPResponder {
@usableFromInline
let trie: RouterTrie<EndpointResponders<Context>>
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Server/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extension Request {
}
}

@available(iOS 16, *)
extension Request {
/// Conditional request which will only be processed if the eTag supplied is not in the
/// `If-None-Match` request header.
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Server/URI+decodeQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import HummingbirdCore
import Logging

@available(iOS 16, *)
extension URI {
/// Decode request query using ``Hummingbird/URLEncodedFormDecoder``.
/// - Parameters
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Storage/MemoryPersistDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import NIOCore
import ServiceLifecycle

/// In memory driver for persist system for storing persistent cross request key/value pairs
@available(iOS 16, *)
public actor MemoryPersistDriver<C: Clock>: PersistDriver where C.Duration == Duration {
public struct Configuration: Sendable {
/// amount of time between each call to tidy
Expand Down
2 changes: 2 additions & 0 deletions Sources/Hummingbird/Storage/PersistDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public import ServiceLifecycle

/// Protocol for driver supporting persistent Key/Value pairs across requests
@available(iOS 16, *)
public protocol PersistDriver: Service {
/// shutdown driver
func shutdown() async throws
Expand Down Expand Up @@ -40,6 +41,7 @@ public protocol PersistDriver: Service {
func remove(key: String) async throws
}

@available(iOS 16, *)
extension PersistDriver {
/// default implemenation of shutdown()
public func shutdown() async throws {}
Expand Down
1 change: 1 addition & 0 deletions Sources/Hummingbird/Utils/DateCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Foundation
///
/// Getting the current date formatted is an expensive operation. This creates a task that will
/// update a cached version of the date in the format as detailed in RFC9110 once every second.
@available(iOS 16, *)
final class DateCache: Service {
final class DateContainer: AtomicReference, Sendable {
let date: String
Expand Down
6 changes: 6 additions & 0 deletions Sources/Hummingbird/Utils/HTTPHeaderDateFormatStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import FoundationEssentials
import Foundation
#endif

@available(iOS 16, *)
extension Date {
init?(httpHeader: String) {
try? self.init(httpHeader, strategy: .rfc9110)
Expand All @@ -30,6 +31,7 @@ extension Date {

struct HTTPHeaderDateParsingError: Error {}

@available(iOS 16, *)
struct HTTPHeaderDateFormatStyle {
let calendar: Calendar

Expand All @@ -40,6 +42,7 @@ struct HTTPHeaderDateFormatStyle {
}
}

@available(iOS 16, *)
extension HTTPHeaderDateFormatStyle: ParseStrategy {
func parse(_ input: String) throws -> Date {
guard let components = self.components(from: input) else {
Expand Down Expand Up @@ -275,6 +278,7 @@ let timezoneOffsetMap: [[UInt8]: Int] = [
Array("PDT".utf8): -7 * 60,
]

@available(iOS 16, *)
extension HTTPHeaderDateFormatStyle: FormatStyle {
//let calendar: Calendar

Expand Down Expand Up @@ -319,10 +323,12 @@ extension HTTPHeaderDateFormatStyle: FormatStyle {
]
}

@available(iOS 16, *)
extension FormatStyle where Self == HTTPHeaderDateFormatStyle {
static var rfc9110: Self { .init() }
}

@available(iOS 16, *)
extension ParseStrategy where Self == HTTPHeaderDateFormatStyle {
static var rfc9110: Self { .init() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public struct HTTPServerBuilder: Sendable {
/// - responder: HTTP responder
/// - onServerRunning: Closure to run once server is up and running
/// - Returns: Server Service
@available(iOS 17, *)
public func buildServer(
configuration: ServerConfiguration,
eventLoopGroup: any EventLoopGroup,
Expand Down
Loading