Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
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(.v11), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v15), .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.

The equivalent versions of macOS and iOS are three versions apart eg 11 and 14, 12 and 15. Which pair of versions should it be?

Copy link
Author

Choose a reason for hiding this comment

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

I've used the earliest versions of each platform that Xcode allowed me to select for minimum deployment version in the project settings. If you want I could raise macOS to 12.

Copy link
Member

Choose a reason for hiding this comment

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

Why can't you set iOS 14?

Copy link
Author

Choose a reason for hiding this comment

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

Xcode doesn't have that option in its drop down. All devices that run iOS 14 also run iOS 15, so there shouldn't be a reason for someone to run iOS 14.

Copy link
Member

Choose a reason for hiding this comment

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

It doesn't mean those users have iOS 15 installed. You are editing Package.swift with a text editor yeah? You can type whatever you want. I'd prefer to stick to the three versions apart and upping the requirement for macOS doesn't seem very sensible.

Copy link
Author

Choose a reason for hiding this comment

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

Package.swift may be editable in a text editor, but someone integrating Hummingbird into an iOS app will very likely be doing that in Xcode, and there's no option in Xcode for them to select a version iOS 14 as minimum.

I'm assuming the lowest version selectable in Xcode would be the minimum that Apple are willing to support, so is this 3-version difference relevant in that case?

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(.v11), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v15), .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(.v11), .iOS(.v15), .macCatalyst(.v15), .tvOS(.v15), .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(macOS 13, iOS 17, tvOS 16, *) 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
private class _URLEncodedFormDecoder: Decoder {
// MARK: Properties

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

@available(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
extension _URLEncodedFormDecoder {
func unboxNil(_ node: URLEncodedFormNode) throws -> Bool {
switch node {
Expand Down Expand Up @@ -686,6 +690,7 @@ extension _URLEncodedFormDecoder {
}
}

@available(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
private class _URLEncodedFormEncoder: Encoder {
var codingPath: [any CodingKey]

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

@available(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
extension Response {
/// Set cookie on response
public mutating func setCookie(_ cookie: Cookie) {
self.headers[values: .setCookie].append(cookie.description)
}
}

@available(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
extension Date {
init?(httpHeader: String) {
try? self.init(httpHeader, strategy: .rfc9110)
Expand All @@ -30,6 +31,7 @@ extension Date {

struct HTTPHeaderDateParsingError: Error {}

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

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

@available(macOS 13, iOS 16, tvOS 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(macOS 13, iOS 16, tvOS 16, *)
extension HTTPHeaderDateFormatStyle: FormatStyle {
//let calendar: Calendar

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

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

@available(macOS 13, iOS 16, tvOS 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
Loading