-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b5b3cb3
Showing
36 changed files
with
1,614 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: Documentation | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
permissions: | ||
contents: read | ||
pages: write | ||
id-token: write | ||
|
||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. | ||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. | ||
concurrency: | ||
group: "pages" | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
publish: | ||
name: Publish Documentation | ||
# TODO: Use `macos-latest` after the macOS 13 image graduates to GA. | ||
# https://github.com/actions/runner-images/issues/7508#issuecomment-1718206371 | ||
runs-on: macos-13 | ||
|
||
environment: | ||
name: github-pages | ||
url: ${{ steps.deployment.outputs.page_url }} | ||
|
||
steps: | ||
- name: Set up GitHub Pages | ||
uses: actions/configure-pages@v3 | ||
- uses: maxim-lobanov/setup-xcode@v1 | ||
with: | ||
xcode-version: latest-stable | ||
- name: Print Swift compiler version | ||
run: "swift --version" | ||
- uses: actions/checkout@v3 | ||
- name: Generate documentation | ||
run: "swift package generate-documentation --target HTTPErrorHandling --disable-indexing --include-extended-types --transform-for-static-hosting --hosting-base-path swift-http-error-handling" | ||
- name: Upload documentation | ||
uses: actions/upload-pages-artifact@v2 | ||
with: | ||
path: ".build/plugins/Swift-DocC/outputs/HTTPErrorHandling.doccarchive" | ||
- name: Deploy to GitHub Pages | ||
id: deployment | ||
uses: actions/deploy-pages@v2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
name: Tests | ||
|
||
on: [push] | ||
|
||
# TODO: Add Windows job after Swift is added to the Windows images [1] or after | ||
# `swift-actions/setup-swift` supports Swift 5.9+ on Windows [2]. | ||
# 1. https://github.com/actions/runner-images/issues/8281 | ||
# 2. https://github.com/swift-actions/setup-swift/pull/470#issuecomment-1718406382 | ||
jobs: | ||
test-macos: | ||
name: Run Tests on macOS | ||
# TODO: Use `macos-latest` after the macOS 13 image graduates to GA. | ||
# https://github.com/actions/runner-images/issues/7508#issuecomment-1718206371 | ||
runs-on: macos-13 | ||
|
||
steps: | ||
- uses: maxim-lobanov/setup-xcode@v1 | ||
with: | ||
xcode-version: latest-stable | ||
- name: Print Swift compiler version | ||
run: "swift --version" | ||
- uses: actions/checkout@v3 | ||
- name: Run tests | ||
run: "swift test --parallel" | ||
|
||
test-linux: | ||
name: Run Tests on Linux | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Print Swift compiler version | ||
run: "swift --version" | ||
- uses: actions/checkout@v3 | ||
- name: Run tests | ||
run: "swift test --parallel" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/config/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# MIT License | ||
|
||
Copyright © 2024 Darren Mo. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"pins" : [ | ||
{ | ||
"identity" : "swift-docc-plugin", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-docc-plugin.git", | ||
"state" : { | ||
"revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", | ||
"version" : "1.3.0" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-docc-symbolkit", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-docc-symbolkit", | ||
"state" : { | ||
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", | ||
"version" : "1.0.0" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-http-types", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-http-types.git", | ||
"state" : { | ||
"revision" : "1827dc94bdab2eb5f2fc804e9b0cb43574282566", | ||
"version" : "1.0.2" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-log", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-log.git", | ||
"state" : { | ||
"revision" : "532d8b529501fb73a2455b179e0bbb6d49b652ed", | ||
"version" : "1.5.3" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-retry", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/fumoboy007/swift-retry.git", | ||
"state" : { | ||
"revision" : "7c571c6b9906ff5c01a25568d4ee169127e16153", | ||
"version" : "0.2.0" | ||
} | ||
} | ||
], | ||
"version" : 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// swift-tools-version: 5.9 | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "swift-http-error-handling", | ||
platforms: [ | ||
.visionOS(.v1), | ||
.macOS(.v13), | ||
.macCatalyst(.v16), | ||
.iOS(.v16), | ||
.tvOS(.v16), | ||
.watchOS(.v9), | ||
], | ||
products: [ | ||
.library( | ||
name: "HTTPErrorHandling", | ||
targets: [ | ||
"HTTPErrorHandling", | ||
] | ||
), | ||
// According to SE-0356, Swift Package Manager does not yet officially support snippet-only dependencies. | ||
// This library product and the corresponding target work around that limitation. The product name is | ||
// prefixed with an underscore to convey that the product was not meant to be externally visible. | ||
.library( | ||
name: "_AdditionalSnippetDependencies", | ||
targets: [ | ||
"_AdditionalSnippetDependencies", | ||
] | ||
), | ||
], | ||
dependencies: [ | ||
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.3.0"), | ||
.package(url: "https://github.com/apple/swift-http-types.git", from: "1.0.2"), | ||
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"), | ||
.package(url: "https://github.com/fumoboy007/swift-retry.git", .upToNextMinor(from: "0.2.0")), | ||
], | ||
targets: [ | ||
.target( | ||
name: "HTTPErrorHandling", | ||
dependencies: [ | ||
.product(name: "DMRetry", package: "swift-retry"), | ||
.product(name: "HTTPTypes", package: "swift-http-types"), | ||
] | ||
), | ||
.testTarget( | ||
name: "HTTPErrorHandlingTests", | ||
dependencies: [ | ||
"HTTPErrorHandling", | ||
.product(name: "HTTPTypes", package: "swift-http-types"), | ||
] | ||
), | ||
.target( | ||
name: "_AdditionalSnippetDependencies", | ||
dependencies: [ | ||
.product(name: "HTTPTypesFoundation", package: "swift-http-types"), | ||
.product(name: "Logging", package: "swift-log"), | ||
] | ||
), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# swift-http-error-handling | ||
|
||
Interpret HTTP responses and handle failures in Swift. | ||
|
||
![Swift 5.9](https://img.shields.io/badge/swift-v5.9-%23F05138) | ||
![Linux, visionOS 1, macOS 13, iOS 16, tvOS 16, watchOS 9](https://img.shields.io/badge/platform-Linux%20%7C%20visionOS%201%20%7C%20macOS%2013%20%7C%20iOS%2016%20%7C%20tvOS%2016%20%7C%20watchOS%209-blue) | ||
![MIT License](https://img.shields.io/github/license/fumoboy007/swift-http-error-handling) | ||
![Automated Tests Workflow Status](https://img.shields.io/github/actions/workflow/status/fumoboy007/swift-http-error-handling/tests.yml?event=push&label=tests) | ||
|
||
## Overview | ||
|
||
In the HTTP protocol, a client sends a request to a server and the server sends a response back to the client. The response contains a [status code](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes) to help the client interpret the response. | ||
|
||
HTTP libraries like `Foundation` pass the response through to the caller without interpreting the response as a success or failure. `HTTPErrorHandling` can help the caller interpret HTTP responses and handle failures. | ||
|
||
The module works with any HTTP library that is compatible with Swift’s [standard HTTP request and response types](https://github.com/apple/swift-http-types). The module can be used on its own in code that directly uses an HTTP library, or the module can be used as a building block by higher-level networking libraries. | ||
|
||
## Example Usage | ||
|
||
```swift | ||
import Foundation | ||
import HTTPErrorHandling | ||
import HTTPTypes | ||
import HTTPTypesFoundation | ||
|
||
let request = HTTPRequest(method: .get, | ||
scheme: "https", | ||
authority: "example.com", | ||
path: "/") | ||
|
||
let responseBody = try await request.retry { request in | ||
let (responseBody, response) = try await URLSession.shared.data(for: request) | ||
try response.throwIfFailed() | ||
return responseBody | ||
} | ||
``` | ||
|
||
See the [documentation](https://fumoboy007.github.io/swift-http-error-handling/documentation/httperrorhandling/) for more examples. |
29 changes: 29 additions & 0 deletions
29
Snippets/Interoperability With Popular HTTP Libraries/RetryHTTPRequestUsingURLSession.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Retry an HTTP request using `URLSession`. | ||
|
||
// snippet.hide | ||
|
||
#if canImport(Darwin) | ||
|
||
// snippet.show | ||
|
||
import Foundation | ||
import HTTPErrorHandling | ||
import HTTPTypes | ||
import HTTPTypesFoundation | ||
|
||
let request = HTTPRequest(method: .get, | ||
scheme: "https", | ||
authority: "example.com", | ||
path: "/") | ||
|
||
let responseBody = try await request.retry { request in | ||
let (responseBody, response) = try await URLSession.shared.data(for: request) | ||
try response.throwIfFailed() | ||
return responseBody | ||
} | ||
|
||
// snippet.hide | ||
|
||
print(responseBody) | ||
|
||
#endif |
25 changes: 25 additions & 0 deletions
25
Snippets/Interpreting HTTP Responses/CustomHTTPResponseInterpretation.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Customize the interpretation of the HTTP response status. | ||
|
||
// snippet.hide | ||
|
||
import HTTPErrorHandling | ||
import HTTPTypes | ||
|
||
let request = HTTPRequest(method: .post, | ||
scheme: "https", | ||
authority: "example.com", | ||
path: "/") | ||
|
||
// snippet.show | ||
|
||
let response = try await perform(request) | ||
try response.throwIfFailed( | ||
successStatuses: [.created], | ||
transientFailureStatuses: .commonTransientFailureStatuses.union([.conflict]) | ||
) | ||
|
||
// snippet.hide | ||
|
||
func perform(_ request: HTTPRequest) async throws -> HTTPResponse { | ||
return HTTPResponse(status: .ok) | ||
} |
22 changes: 22 additions & 0 deletions
22
Snippets/Interpreting HTTP Responses/DefaultHTTPResponseInterpretation.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Throw an error if the HTTP response represents a failure. | ||
|
||
// snippet.hide | ||
|
||
import HTTPErrorHandling | ||
import HTTPTypes | ||
|
||
let request = HTTPRequest(method: .get, | ||
scheme: "https", | ||
authority: "example.com", | ||
path: "/") | ||
|
||
// snippet.show | ||
|
||
let response = try await perform(request) | ||
try response.throwIfFailed() | ||
|
||
// snippet.hide | ||
|
||
func perform(_ request: HTTPRequest) async throws -> HTTPResponse { | ||
return HTTPResponse(status: .ok) | ||
} |
40 changes: 40 additions & 0 deletions
40
Snippets/Interpreting HTTP Responses/HTTPApplicationErrorWithResponseBody.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Attach the response body to ``HTTPApplicationError`` and access it later. | ||
|
||
// snippet.hide | ||
|
||
import Foundation | ||
import HTTPErrorHandling | ||
import HTTPTypes | ||
|
||
let request = HTTPRequest(method: .get, | ||
scheme: "https", | ||
authority: "example.com", | ||
path: "/") | ||
|
||
// snippet.show | ||
|
||
do { | ||
let (responseBody, response) = try await perform(request) | ||
try await response.throwIfFailed { | ||
return try await deserializeFailureDetails(from: responseBody) | ||
} | ||
} catch let error as HTTPApplicationError<MyFailureDetails> { | ||
let failureDetails = error.responseBody | ||
doSomething(with: failureDetails) | ||
} | ||
|
||
// snippet.hide | ||
|
||
func perform(_ request: HTTPRequest) async throws -> (Data, HTTPResponse) { | ||
return (Data(), HTTPResponse(status: .ok)) | ||
} | ||
|
||
struct MyFailureDetails { | ||
} | ||
|
||
func deserializeFailureDetails(from responseBody: Data) async throws -> MyFailureDetails { | ||
return MyFailureDetails() | ||
} | ||
|
||
func doSomething(with failureDetails: MyFailureDetails) { | ||
} |
Oops, something went wrong.