apple / apple/swift-http-types

Conversion from relative HTTPRequest to absolute Foundation URL

Open
#36 5 comments 0 reactions 0 assignees View on GitHub
kind/enhancement
Dominant language
Swift
Stars
1k
Forks
80
Avg merge
2d 4h
Merged PRs (30d)
12

Description

Hello,

This issue is a feature request for a new API in the HTTPTypesFoundation module:

```swift
extension HTTPRequest {
public func url(baseURL: URL) -> URL?
}
```

---

I met a need for this API while using http://github.com/apple/swift-openapi-generator

When writing a [`ClientMiddleware`](https://swiftpackageindex.com/apple/swift-openapi-runtime/0.3.6/documentation/openapiruntime/clientmiddleware) that processes http requests performed through `URLSession`, I need an absolute `Foundation.URL` in order to use various services such as [`HTTPCookieStorage`](https://developer.apple.com/documentation/foundation/httpcookiestorage).

This package defines a [`HTTPRequest.url`](https://github.com/apple/swift-http-types/blob/1.0.0/Sources/HTTPTypesFoundation/HTTPRequest%2BURL.swift#L22) property that looks very promising.

But the `HTTPRequest` I get from OpenAPIRuntime is not absolute. It is relative to a base URL, and its `url` property is nil:

```swift
struct MyMiddleware: ClientMiddleware {
func intercept(
_ request: HTTPRequest,
body requestBody: HTTPBody?,
baseURL: URL,
operationID: String,
next: (HTTPRequest, HTTPBody?, URL) async throws -> (HTTPResponse, HTTPBody?)
) async throws -> (HTTPResponse, HTTPBody?)
{
print(request.url) // nil
}
}
```

Since my requests are performed through `URLSession`, I was pretty sure to find some code that turns a (request, baseURL) pair into an absolute `URL`, suitable for `URLRequest`. Indeed, it is [there](https://github.com/apple/swift-openapi-urlsession/blob/0.3.0/Sources/OpenAPIURLSession/URLSessionTransport.swift#L185-L208).

This code is not public, so I defined my own version, inspired from the above implementation:

```swift
extension HTTPRequest {
/// Returns an absolute URL.
///
/// Inspired from
func url(baseURL: URL) -> URL? {
guard
var baseUrlComponents = URLComponents(string: baseURL.absoluteString),
let requestUrlComponents = URLComponents(string: path ?? "")
else {
return nil
}

let path = requestUrlComponents.percentEncodedPath
baseUrlComponents.percentEncodedPath += path
baseUrlComponents.percentEncodedQuery = requestUrlComponents.percentEncodedQuery
return baseUrlComponents.url
}
}
```

---

Since the implementation is not quite trivial, I believe it is a good candidate for inclusion in `HTTPTypesFoundation`.

What do you think?

Contributor guide

Open the contributing guide

Research direction

Start with Sources/HTTPTypesFoundation/HTTPRequest+URL.swift and compare its existing URL handling with the referenced URLSessionTransport.swift implementation. Define the requested HTTPRequest.url(baseURL:) API and verify that it produces an absolute Foundation URL for the relative request and base URL cases described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
api
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.