Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
29 changes: 29 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,32 @@ jobs:
release-builds:
name: Release builds
uses: apple/swift-nio/.github/workflows/release_builds.yml@main

construct-linkage-test-matrix:
name: Construct linkage matrix
runs-on: ubuntu-latest
outputs:
linkage-test-matrix: '${{ steps.generate-matrix.outputs.linkage-test-matrix }}'
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- id: generate-matrix
run: echo "linkage-test-matrix=$(curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/generate_matrix.sh | bash)" >> "$GITHUB_OUTPUT"
env:
MATRIX_LINUX_SETUP_COMMAND: apt-get update -y && apt-get install -yq jq && git config --global --add safe.directory /async-http-client
MATRIX_LINUX_COMMAND: ./scripts/run-linkage-test.sh
MATRIX_LINUX_5_10_ENABLED: false
MATRIX_LINUX_6_0_ENABLED: false
MATRIX_LINUX_6_1_ENABLED: false
MATRIX_LINUX_NIGHTLY_NEXT_ENABLED: false
MATRIX_LINUX_NIGHTLY_MAIN_ENABLED: false

linkage-test:
name: Linkage test
needs: construct-linkage-test-matrix
uses: apple/swift-nio/.github/workflows/swift_test_matrix.yml@main
with:
name: "Linkage test"
matrix_string: '${{ needs.construct-linkage-test-matrix.outputs.linkage-test-matrix }}'
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ let package = Package(
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-distributed-tracing.git", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-configuration.git", from: "1.0.0"),
// Disable all traits to prevent linking Foundation
.package(url: "https://github.com/apple/swift-configuration.git", from: "1.0.0", traits: []),
Comment thread
fabianfett marked this conversation as resolved.
.package(url: "https://github.com/apple/swift-service-context.git", from: "1.1.0"),
],
targets: [
Expand All @@ -68,7 +69,7 @@ let package = Package(
.product(name: "NIOSSL", package: "swift-nio-ssl"),
.product(name: "NIOHTTPCompression", package: "swift-nio-extras"),
.product(name: "NIOSOCKS", package: "swift-nio-extras"),
.product(name: "NIOTransportServices", package: "swift-nio-transport-services"),
.product(name: "NIOTransportServices", package: "swift-nio-transport-services", condition: .when(platforms: [.macOS, .iOS, .tvOS, .watchOS, .macCatalyst, .visionOS])),
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
.product(name: "Atomics", package: "swift-atomics"),
.product(name: "Algorithms", package: "swift-algorithms"),
.product(name: "Configuration", package: "swift-configuration"),
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import NIOCore
import NIOHTTP1
import Tracing

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension HTTPClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import NIOHTTP1
import NIOSSL
import ServiceContextModule

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension HTTPClientRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
//
//===----------------------------------------------------------------------===//

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension HTTPClientRequest {
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
import NIOCore
import NIOHTTP1

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

/// A representation of an HTTP response for the Swift Concurrency HTTPClient API.
///
Expand Down
7 changes: 6 additions & 1 deletion Sources/AsyncHTTPClient/BasicAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import NIOHTTP1

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Generates base64 encoded username + password for http basic auth.
///
/// - Parameters:
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/DeconstructedURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
//
//===----------------------------------------------------------------------===//

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

struct DeconstructedURL {
var scheme: Scheme
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/FileDownloadDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import NIOCore
import NIOHTTP1
import NIOPosix

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

/// Handles a streaming download to a given file path, allowing headers and progress to be reported.
public final class FileDownloadDelegate: HTTPClientResponseDelegate {
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/FoundationExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
// Extensions which provide better ergonomics when using Foundation types,
// or by using Foundation APIs.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

extension HTTPClient.Cookie {
/// The cookie's expiration date.
Expand Down
11 changes: 10 additions & 1 deletion Sources/AsyncHTTPClient/HTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===//

import Atomics
import Foundation
import Dispatch
import Logging
import NIOConcurrencyHelpers
import NIOCore
Expand All @@ -22,9 +22,18 @@ import NIOHTTPCompression
import NIOPosix
import NIOSSL
import NIOTLS

#if canImport(Network)
import NIOTransportServices
#endif
import Tracing

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

extension Logger {
private func requestInfo(_ request: HTTPClient.Request) -> Logger.Metadata.Value {
"\(request.method) \(request.url)"
Expand Down
19 changes: 18 additions & 1 deletion Sources/AsyncHTTPClient/HTTPHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//

import Algorithms
import Foundation
import Logging
import NIOConcurrencyHelpers
import NIOCore
Expand All @@ -22,6 +21,12 @@ import NIOPosix
import NIOSSL
import Tracing

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

extension HTTPClient {
/// A request body.
public struct Body: Sendable {
Expand Down Expand Up @@ -880,7 +885,13 @@ extension URL {
/// - socketPath: The path to the unix domain socket to connect to.
/// - uri: The URI path and query that will be sent to the server.
public init?(httpURLWithSocketPath socketPath: String, uri: String = "/") {
#if canImport(Darwin)
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
guard let host = socketPath.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { return nil }
#else
guard let urlComponents = URLComponents(string: socketPath), let host = urlComponents.encodedHost else {
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
return nil
}
#endif
var urlString: String
if uri.hasPrefix("/") {
urlString = "http+unix://\(host)\(uri)"
Expand All @@ -895,7 +906,13 @@ extension URL {
/// - socketPath: The path to the unix domain socket to connect to.
/// - uri: The URI path and query that will be sent to the server.
public init?(httpsURLWithSocketPath socketPath: String, uri: String = "/") {
#if canImport(Darwin)
guard let host = socketPath.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { return nil }
#else
guard let urlComponents = URLComponents(string: socketPath), let host = urlComponents.encodedHost else {
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
return nil
}
#endif
var urlString: String
if uri.hasPrefix("/") {
urlString = "https+unix://\(host)\(uri)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@

import NIOCore
import NIOHTTP1
import NIOTransportServices

#if canImport(Network)
import Network
import NIOTransportServices
#endif

extension HTTPClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

#if canImport(Network)

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
import Dispatch
import Network
import NIOCore
import NIOSSL
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/RedirectState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

import NIOHTTP1

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

typealias RedirectMode = HTTPClient.Configuration.RedirectConfiguration.Mode

Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncHTTPClient/RequestBag+StateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
import NIOCore
import NIOHTTP1

#if canImport(FoundationEssentials)
import struct FoundationEssentials.URL
#else
import struct Foundation.URL
#endif

extension HTTPClient {
/// The maximum body size allowed, before a redirect response is cancelled. 3KB.
Expand Down
2 changes: 2 additions & 0 deletions Tests/LinkageTest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.build
Package.resolved
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
18 changes: 18 additions & 0 deletions Tests/LinkageTest/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// swift-tools-version: 6.2

import PackageDescription

let package = Package(
name: "linkage-test",
dependencies: [
.package(name: "async-http-client", path: "../..")
],
targets: [
.executableTarget(
name: "linkageTest",
dependencies: [
.product(name: "AsyncHTTPClient", package: "async-http-client")
]
)
]
)
17 changes: 17 additions & 0 deletions Tests/LinkageTest/Sources/linkageTest/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the AsyncHTTPClient open source project
//
// Copyright (c) 2026 Apple Inc. and the AsyncHTTPClient project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import AsyncHTTPClient

print("\(HTTPClient.shared)")
58 changes: 58 additions & 0 deletions scripts/run-linkage-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the AsyncHTTPClient open source project
##
## Copyright (c) 2026 Apple Inc. and the AsyncHTTPClient project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
set -eu

# Validate that we're running on Linux
if [[ "$(uname -s)" != "Linux" ]]; then
echo "Error: This script must be run on Linux. Current OS: $(uname -s)" >&2
exit 1
fi

echo "Running on Linux - proceeding with linkage test..."

# Build the linkage test package
echo "Building linkage test package..."
swift build --package-path Tests/LinkageTest

# Check the architecture and build path
ARCH=$(uname -m)
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
if [[ "$ARCH" == "x86_64" ]]; then
BUILD_PATH="Tests/LinkageTest/.build/x86_64-unknown-linux-gnu/debug/linkageTest"
Comment thread
madsodgaard marked this conversation as resolved.
Outdated
elif [[ "$ARCH" == "aarch64" ]]; then
BUILD_PATH="Tests/LinkageTest/.build/aarch64-unknown-linux-gnu/debug/linkageTest"
else
echo "Error: Unsupported architecture: $ARCH" >&2
exit 1
fi

# Verify the binary exists
if [[ ! -f "$BUILD_PATH" ]]; then
echo "Error: Built binary not found at $BUILD_PATH" >&2
exit 1
fi

echo "Checking linkage for binary: $BUILD_PATH"

# Run ldd and check if libFoundation.so is linked
LDD_OUTPUT=$(ldd "$BUILD_PATH")
echo "LDD output:"
echo "$LDD_OUTPUT"

if echo "$LDD_OUTPUT" | grep -q "libFoundation.so"; then
echo "Error: Binary is linked against libFoundation.so - this indicates incorrect linkage. Ensure the full Foundation is not linked on Linux when default traits are disabled." >&2
exit 1
else
echo "Success: Binary is not linked against libFoundation.so - linkage test passed."
fi