Skip to content
Declarative HTTP networking, designed for SwiftUI
Branch: master
Clone or download
carson-katri v1.1.2 (#10)
* .gitignore fix
* codecov
* Improved `Json` Implementation (#9)
Latest commit 1996de0 Aug 9, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.swiftpm/xcode v1.1.2 (#10) Aug 9, 2019
Request.xcodeproj v1.1.2 (#10) Aug 9, 2019
Resources v1.1.2 (#10) Aug 9, 2019
Sources v1.1.2 (#10) Aug 9, 2019
Tests v1.1.2 (#10) Aug 9, 2019
.gitignore v1.1.2 (#10) Aug 9, 2019
.travis.yml v1.1.2 (#10) Aug 9, 2019 Documentation Jul 13, 2019
LICENSE Fix copyright Jul 13, 2019
Package.swift Separate Request and Json libraries Jul 13, 2019 v1.1.2 (#10) Aug 9, 2019


swift 5.1 SwiftUI iOS macOS tvOS Build Status codecov

Installation - Getting Started - Building a Request - Codable - How it Works - Request Groups - Request Chains - Json - Contributing - License

Using with SwiftUI


swift-request can be installed via the Swift Package Manager.

In Xcode 11, go to File > Swift Packages > Add Package Dependency..., then paste in

Now just import Request, and you're ready to Get Started

Getting Started

The old way:

var request = URLRequest(url: URL(string: "")!)
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: url!) { (data, res, err) in
    if let data = data {
    } else if let error = error {

The declarative way:

Request {
.onData { data in
.onError { error in

The benefit of declaring requests becomes abundantly clear when your data becomes more complex:

Request {
        "title": "foo",
        "body": "bar",
        "usedId": 1

Once you've built your Request, you can specify the response handlers you want to use. .onData, .onString, .onJson, and .onError are available. You can chain them together to handle multiple response types, as they return a modified version of the Request. You can also use .response, which is an ObservableObject for use with Combine and/or SwiftUI.

To perform the Request, just use .call(). This will run the Request, and give you the response when complete.

Building a Request

There are many different tools available to build a Request:

  • Url

Exactly one must be present in each Request

Url(protocol: .secure, url: "")
  • Method

Sets the MethodType of the Request (.get by default)

Method(.get) // Available: .get, .head, .post, .put, .delete, .connect, .options, .trace, and .patch 
  • Header

Sets an HTTP header field

Header.Any(key: "Custom-Header", value: "value123")
Header.Authorization(.basic(username: "carsonkatri", password: "password123"))
Header.Host("", port: "8000")
  • Query

Creates the query string

Query(["key": "value"]) // ?key=value
  • Body

Sets the request body

Body(["key": "value"])
  • RequestParam

Add a param directly

Important: You must create the logic to handle a custom RequestParam. You may also consider adding a case to RequestParamType. If you think your custom parameter may be useful for others, see Contributing


Let's look at an example. Here we define our data:

struct Todo: Codable {
    let title: String
    let completed: Bool
    let id: Int
    let userId: Int

Now we can use AnyRequest to pull an array of Todos from the server:

AnyRequest<[Todo]> {
.onObject { todos in ... }

In this case, onObject gives us [Todo]? in response. It's that easy to get data and decode it.

Request is built on AnyRequest, so they support all of the same parameters.

If you use onObject on a standard Request, you will receive Data in response.

How it Works

The body of the Request is built using the RequestBuilder @_functionBuilder.

It merges each RequestParam in the body into one CombinedParam object. This contains all the other params as children.

When you run .call(), the children are filtered to find the Url, and any other optional parameters that may have been included.

For more information, see RequestBuilder.swift and Request.swift

Request Groups

RequestGroup can be used to run multiple Requests simulataneously. You get a response when each Request completes (or fails)

RequestGroup {
    Request {
    Request {
    Request {
.onData { (index, data) in

Request Chains

RequestChain is used to run multiple Requests one at a time. When one completes, it passes its data on to the next Request, so you can use it to build the Request. can optionally accept a callback that gives you all the data of every Request when completed.

Note: You must use Request.chained to build your Request. This gives you access to the data and errors of previous Requests.

RequestChain {
    Request.chained { (data, errors) in
    Request.chained { (data, errors) in
        let json = Json(data[0]!)
        return Url("\(json?[0]["id"].int ?? 0)")
.call { (data, errors) in


swift-request includes support for Json. Json is used as the response type in the onJson callback on a Request object.

You can create Json by parsing a String or Data:

Json("{\"firstName\":\"Carson\"}".data(using: .utf8))

You can subscript Json as you would expect:

myJson["firstName"].string // "Carson"

It also supports dynamicMemberLookup, so you can subscript it like so:

myJson.firstName.string // "Carson"

You can use .string, .int, .double, .bool, and .array to retrieve values in a desired type.

Note: These return non-optional values. If you want to check for nil, you can use .stringOptional, .intOptional, etc.





You can’t perform that action at this time.