GithubHelp home page GithubHelp logo

carson-katri / swift-request Goto Github PK

View Code? Open in Web Editor NEW
722.0 15.0 41.0 704 KB

Declarative HTTP networking, designed for SwiftUI

License: MIT License

Swift 100.00%
swiftui networking http declarative dsl functionbuilder

swift-request's Introduction

Request

swift 5.1 SwiftUI iOS macOS tvOS Build codecov

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

Using with SwiftUI

Installation

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

In Xcode 11, go to File > Swift Packages > Add Package Dependency..., then paste in https://github.com/carson-katri/swift-request

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

Getting Started

The old way:

var request = URLRequest(url: URL(string: "https://jsonplaceholder.typicode.com/todos")!)
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 {
        ...
    }
}
task.resume()

The declarative way:

Request {
    Url("https://jsonplaceholder.typicode.com/todo")
    Header.Accept(.json)
}
.onData { data in
    ...
}
.onError { error in
    ...
}
.call()

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

Request {
    Url("https://jsonplaceholder.typicode.com/posts")
    Method(.post)
    Header.ContentType(.json)
    Body(Json([
        "title": "foo",
        "body": "bar",
        "usedId": 1
    ]).stringified)
}

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.

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

Request also conforms to Publisher, so you can manipulate it like any other Combine publisher (read more):

let cancellable = Request {
    Url("https://jsonplaceholder.typicode.com/todo")
    Header.Accept(.json)
}
.sink(receiveCompletion: { ... }, receiveValue: { ... })

Building a Request

There are many different tools available to build a Request:

  • Url

Exactly one must be present in each Request

Url("https://example.com")
Url(protocol: .secure, url: "example.com")
  • 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.Accept(.json)
Header.Authorization(.basic(username: "carsonkatri", password: "password123"))
Header.CacheControl(.noCache)
Header.ContentLength(16)
Header.ContentType(.xml)
Header.Host("en.example.com", port: "8000")
Header.Origin("www.example.com")
Header.Referer("redirectfrom.example.com")
Header.UserAgent(.firefoxMac)
  • Query

Creates the query string

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

Sets the request body

Body(["key": "value"])
Body("myBodyContent")
Body(myJson)
  • Timeout

Sets the timeout for a request or resource:

Timeout(60)
Timeout(60, for: .request)
Timeout(30, for: .resource)
  • 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

Codable

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]> {
    Url("https://jsonplaceholder.typicode.com/todos")
}
.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.

Combine

Request and RequestGroup both conform to Publisher:

Request {
    Url("https://jsonplaceholder.typicode.com/todos")
}
.sink(receiveCompletion: { ... }, receiveValue: { ... })

RequestGroup {
    Request {
        Url("https://jsonplaceholder.typicode.com/todos")
    }
    Request {
        Url("https://jsonplaceholder.typicode.com/posts")
    }
    Request {
        Url("https://jsonplaceholder.typicode.com/todos/1")
    }
}
.sink(receiveCompletion: { ... }, receiveValue: { ... })

Request publishes the result using URLSession.DataTaskPublisher. RequestGroup collects the result of each Request in its body, and publishes the array of results.

You can use all of the Combine operators you'd expect on Request:

Request {
    Url("https://jsonplaceholder.typicode.com/todos")
}
.map(\.data)
.decode([Todo].self, decoder: JSONDecoder())
.sink(receiveCompletion: { ... }, receiveValue: { ... })

However, Request also comes with several convenience Publishers to simplify the process of decoding:

  1. objectPublisher - Decodes the data of an AnyRequest using JSONDecoder
  2. stringPublisher - Decodes the data to a String
  3. jsonPublisher - Converts the result to a Json object

Here's an example of using objectPublisher:

AnyRequest<[Todo]> {
    Url("https://jsonplaceholder.typicode.com/todos")
}
.objectPublisher
.sink(receiveCompletion: { ... }, receiveValue: { ... })

This removes the need to constantly use .map.decode to extract the desired Codable result.

To handle errors, you can use the receiveCompletion handler in sink:

Request {
    Url("https://jsonplaceholder.typicode.com/todos")
}
.sink(receiveCompletion: { res in
    switch res {
    case let .failure(err):
        // Handle `err`
    case .finished: break
    }
}, receiveValue: { ... })

How it Works

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

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 {
        Url("https://jsonplaceholder.typicode.com/todos")
    }
    Request {
        Url("https://jsonplaceholder.typicode.com/posts")
    }
    Request {
        Url("https://jsonplaceholder.typicode.com/todos/1")
    }
}
.onData { (index, data) in
    ...
}
.call()

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.

RequestChain.call 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
        Url("https://jsonplaceholder.typicode.com/todos")
    }
    Request.chained { (data, errors) in
        let json = Json(data[0]!)
        return Url("https://jsonplaceholder.typicode.com/todos/\(json?[0]["id"].int ?? 0)")
    }
}
.call { (data, errors) in
    ...
}

Repeated Calls

.update is used to run additional calls after the initial one. You can pass it either a number or a custom Publisher. You can also chain together multiple .updates. The two .updates in the following example are equivalent, so the end result is that the Request will be called once immediately and twice every 10 seconds thereafter.

Request {
    Url("https://jsonplaceholder.typicode.com/todo")
}
.update(every: 10)
.update(publisher: Timer.publish(every: 10, on: .main, in: .common).autoconnect())
.call()

If you want to use Request as a Publisher, use updatePublisher:

Request {
    Url("https://jsonplaceholder.typicode.com/todo")
}
.updatePublisher(every: 10)
.updatePublisher(publisher: ...)
.sink(receiveCompletion: { ... }, receiveValue: { ... })

Unlike update, updatePublisher does not send a value immediately, but will wait for the first value from the Publisher.

Json

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\"}")
Json("{\"firstName\":\"Carson\"}".data(using: .utf8))

You can subscript Json as you would expect:

myJson["firstName"].string // "Carson"
myComplexJson[0]["nestedJson"]["id"].int

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

myJson.firstName.string // "Carson"
myComplexJson[0].nestedJson.id.int

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.

Contributing

See CONTRIBUTING

License

See LICENSE

swift-request's People

Contributors

carson-katri avatar egorkolyshkin avatar ezraberch avatar o-nnerb avatar pokryfka avatar rain2540 avatar vakechu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-request's Issues

This is a feature request for several improvements

  • New declarative backend implementation;
  • More control over URLSession and URLRequest objects;
  • Support to edit URLSessionConfiguration;
  • New Tasks (replacement for Request) based on URLSession methods;
  • Support for async await;
  • TaskModifiers;
  • TaskInterceptors;

I have this all implemented. I would like to make this contribution if possible.

What you say @carson-katri ?

I think that something may have break changes, especially the way that was implemented the Request and GroupRequest. But this new implementation support all features that this project already have.

updatePublisher internal protection

Hi,

I would like to use updatePublisher for repeated calls (as per documentation), but it looks like it is unaccessible due internal protection level.

Is this a bug?

Issue with subscript not existing causing crash

Ive stumbled upon a case where my server returned a partially formed body that doesnt include a key.
I see no way in the api to safely access a subscript that may not exist.
Json line 65: json.jsonData = (jsonData as! [String: Any])[s]!

My code:

 .onJson { j in
            print(j)
            if j.stringified?.contains("script") != nil { // added to get around the crash
            $script.wrappedValue = j["script"].string
            } // added
        }

Id expect nil as opposed to a crash. I think thats what js would do, just return undefined for a non existing key instead of treating it as an error.
In my xp, though I use force unwraps , I nearly always end up reverting them.

RequestView refresh?

I'm using RequestView to fetch data from a News API. I attempted to use your example of adding a Query string and update the number incrementally like in your example but it didn't actually refresh the view.

My query string is Query(["q": text, "apiKey": "API_KEY"]) where text is my variable for a TextField string. I need to refresh the RequestView when my key changes. I've been unable to do so using RequestView but was able to using URLRequest manually and calling a func load() on my TextField's onCommit function. I'd really like to keep using RequestView in my project because it's very useful and easy to use for a beginner like myself! 😄

RequestView code not updating here
Working code without RequestView here

Support for `Json?`, and `String?` as the response in a `RequestView`

Currently, RequestView only supports Data? as a return type.

This enhancement is to allow Json? and String? as responses as well by adding more initializers:

RequestView(myRequest) { (data: Data?) in ... }
RequestView(myRequest) { (string: String?) in ... }
RequestView(myRequest) { (json: Json?) in ... }

Discussion: New structure for declarative programming

I would like to suggest a better and clean way to create declarative objects.

The idea is to make RequestParam a generic protocol with a static function like that:

protocol RequestParam {
    static func _buildRequest(_ param: Self /* or RequestParam */) -> URLRequest
    // or
    static func _buildRequest(_ param: Self, _ request: URLRequest) -> URLRequest /* or Void */
}

struct Body: RequestParam {
    private let data: Data?
    /// Creates the `Body` from key-value pairs
    public init(_ dict: [String:Any]) {
        self.value = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
    }
    
    /// Creates the `Body` from an `Encodable` type using `JSONEncoder`
    public init<T: Encodable>(_ value: T) {
        self.value = try? JSONEncoder().encode(value)
    }
    
    /// Creates the `Body` from a `String`
    public init(_ string: String) {
        self.value = string.data(using: .utf8)
    }

    public static func _buildRequest(_ param: Self, _ request: URLRequest) -> URLRequest {
        var request = request
        request.httpBody = param.data
        return request
    }
}

How to parse array inside array?

I have a json like this and I want to make a RequestView loading all categories
{
"error": false,
"message": "Success",
"data": [
{
"id": 5,
"name": "Man",
"image": "phpSLlQP3.png",
"has_children": "yes"
},
{
"id": 6,
"name": "Woman",
"image": "php1g8L0Q.png",
"has_children": "no"
}
}

RequestError not passed back to .onError handler?

First: love the library. I learned a lot about Combine just browsing.

In my first test project, correct usage just works. (!) When I introduce a deliberate error in the URL, I don't get a call to the .onError handler. Instead, the system logs a lot of stuff. (Below.) What can I do to ensure that my app can handle such errors?

Connection 1: received failure notification
Connection 1: failed to connect 12:8, reason -1
Connection 1: encountered error(12:8)
Task <D69B0AC6-...>.<1> HTTP load failed, 0/0 bytes (error code: -1003 [12:8])
Task <D69B0AC6-...>.<1> finished with error [-1003] 
Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." 
UserInfo={... useful stuff in here but it's not getting to my handler ... }

How to refresh a RequestView?

swift-request is brilliant , especially when using it with SwiftUI.

But I can't find a way to refresh a RequestView , cloud you give me some clue?

Thank.

`async`/`await` support

The basic idea is that you can await any Request using call():

let getTodos = AnyRequest<[Todo]> {
  Url("todos.com/api")
}
let todos = try await getTodos.call()

callAsFunction could also be added to simplify this demo to:

let todos = try await getTodos()

This opens up new opportunities for crafting readable APIs:

enum API {
  // These can be used as async throwing functions:
  static let getPosts = AnyRequest<[Post]> {
    Url("...")
  }
  static let getUsers = AnyRequest<[User]> {
    Url("...")
  }
  // Real functions can also be added:
  static func getPost(id: Int) async throws -> Post {
    try await AnyRequest<Post> {
      Url(".../\(id)")
    }()
  }
}

// Simply use these as functions:
let posts = try await API.getPosts()
let users = try await API.getUsers()
let post = try await API.getPost(id: 0)

async let gives the power of concurrency:

async let posts = API.getPosts()
async let users = API.getUsers()
let authored = zip(try await callTodos, try await callAsFunctionTodos)

Question: Is there support for progress for transfers?

I've done some looking and dont see any way to do what URLSessionTaskDelegate enables.

    	_ session: URLSession, 
        task: URLSessionTask, 
        didSendBodyData bytesSent: Int64, 
        totalBytesSent: Int64, 
        totalBytesExpectedToSend: Int64
     )```
Im brainstorming what the api might look like and how it could work.
I assume this all wraps URLSessionTask so it feels it should be doable, but I wanted your thoughts before I went far.

Improved `Json` support

Rewrite Json to rely more heavily on the builtin JSONSerialization. All it would do is handle subscripting and retrieving values.

JsonBuilder and JsonProperty would still be available.

JsonBuilder would support tuples as well:

Json {
    ("key", "value")
}

Provide optionals for .string, .int, etc. Possible named .stringOptional?

How to extend request?

I am new to Swift and not that familiar with the function builder, but I love this library and wanted to use it.

I was wondering how can I have a Request shared in my application that already has some things preset like the headers and the URL.

I am trying to create a centralized place for my API calls and didn't want to continue including repetitive code in the request body all over the app

Improvements on RequestError

  • The actual implementation of RequestError should return the connection error or when succeed the error data.
  • The RequestError should implement the Error protocol, so the developers can cast the error as RequestError.

HTTP 403 when trying to post dictionary body

Hi! I've recently decided to switch over from AlamoFire to this because it's much more Swift-ey, but I've run into the following issue:

Back in AlamoFire I'd send my request body with
Alamofire.request("https://myserver.com", method: .post, parameters: [ "title": "foo", "body": "bar", "userId": 18" ], encoding: JSONEncoding.default)

and it worked perfectly, so I rewrote this to:

Request {
        Url("https://myserver.com")
        Method(.post)
        Body([
            "title": "foo",
            "body": "bar",
            "userId": 18
        ])
}

But this however, throws back a 403 forbidden. I can't seem to understand why this happens as it worked fine using AlamoFire, and if I change the body to use an encodable instead like so:

struct Test: Codable {
        let title: String
        let body: String
        let userId: Int
    }
    
    Request {
        Url("https://api.loucee.dev/register")
        Method(.post)
        Body(Test(title: "foo", body: "bar", userId: 18))
    }

Everything works fine again! But the issue with this is that I have a lot of different requests to make in my app, and I rather not have 30 or so codables laying around...

My question is, what is causing this weird behaviour? Can I resolve it somehow?

二次封装

这个请求能够二次封装吗,我想把请求头,公共参数封装到一起,还有一些公共设置,例如请求超时时间。然后做一个可以返回模型也可以返回模型的封装,但是没有封装好

Json: Access nested optional value

Hi there,

Thanks for the library.

I am using an api which returns the following json :

{
  "object": {
     "name": "Bob",
        // ...
  },
  "some": "other value"
}

The object key can sometimes be empty.

However, I want to access the name key using my Json object. But when the object is empty, my app crashes because of course, it cannot get to the name key (Could not cast value of type 'NSNull' (0x...........) to 'NSDictionary').

I can't figure out how to test for this.

Thanks for the help.

`buildIf`

Build optional would allow the following to be possible:

Request {
    Url("https://example.com/data")
    if requiresAuth {
        Header.Authorization(.basic(username: "user1", password: "password123"))
    }
}

RequestImage remove animation

Setting nil doesn't seem to remove animation from RequestImage, testing on iOS 14.

RequestImage(Url("url_here"))
   .animation(nil)

400

first time use ,then 400 ,the urlString and query is right, thanks.

Is there an example for this project?🌟🌟

image

image

Custom decoder for date

How would I go about decoding custom data, such as custom formatted dates?
Do we have access to JSONDecoder so we can do something like this: ?

struct Event: Codable {
    var name: String?
    var createdDate: Date?
}

extension DateFormatter {
    static let dateFormatter: DateFormatter = {
     let formatter = DateFormatter()
     formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
      return formatter
    }()
}

let decoder: JSONDecoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(.dateFormatter)

Question: RequestView JSON API

Having an issue loading JSON data with RequestView. My test data works fine but when I use the API data it's not returning anything. I'm using newsapi.org. I'm getting error RequestError(statusCode: 401, error: Optional(158 bytes)) and my API key is correct.

struct News : Codable {
    var articles : [Article]
}

struct Article : Codable, Hashable {
    let description : String?
    let title : String?
    let author: String?
    let source: Source
    let content: String?
    let publishedAt: String?
}

struct Source: Codable {
    let name: String?
}

struct ContentView: View {
    
    var body: some View {
        
        // This works using an example file
        RequestView(News.self, Request {
            Url("https://raw.githubusercontent.com/ca13ra1/data/main/data.json")
            Method(.get)
            Header.Accept(.json)
        }) { news in
            List(news?.articles ?? [], id: \.self) { article in
                Text(article.title ?? "")
            }
            Text("")
        }
        
        /*
        This does not work
         RequestView(News.self, Request {
             Url("https://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY")
             Method(.get)
             Header.Accept("application/json")
             Header.ContentType(.json)
             Header.CacheControl(.noCache)
             Header.UserAgent(.safari)
         }) { news in
             List(news?.articles ?? [], id: \.self) { article in
                 Text(article.title ?? "")
             }
             Text("")
         }
        */
    }
}

Get IP address of Client that is submitting the request

Is there a way to get the IP address of the Client machine or browser that is submitting the request? I am initialing a request from SwiftWebUI and I would like the IP address of the client machine.

    Request {
        Url("https://example.com/service")
        Method(.get)
        Header.Accept(.json)
    }
   .onJson { json in
        print(json)
    }

ios10 cannot use Json

Compiling for iOS 10.0, but module 'Json' has a minimum deployment target of iOS 13.0

Web Sockets

Socket

Web socket support is a large task, so it may be a while. Here's an example of what the syntax could look like:

let ws = Socket {
    // Implicit "wss://"
    Url("echo.websocket.org")
    Header.Authorization(.basic(username: "username", password: "pass123"))
    ...
}
.onOpen { ... }
.onClose { reason in ... }
.onData { data in ... }
.onString { string in ... }
.onJson { json in ... }
.onError { err in ... }

ws.send("Hello world")
ws.send(myData)
// Sometime later
ws.close()

onClose would return a SocketCloseEvent, which contains the code (URLSessionWebSocketTask.CloseCode) and the reason. You could pass this into the .close method:

ws.close(SocketCloseEvent(code: .goingAway, reason: "I had a problem!"))
ws.close(code: .goingAway, reason: nil)

This will be built atop URLSessionWebSocketTask, available in iOS 13. Custom frames will not be supported with this implementation.

AnySocket

A Socket with Codable support. It could be used with the onObject callback:

struct Message: Decodable {
    let sender: String
    let body: String
}
AnySocket<Message> {
    Url("messaging.example.com")
}
.onObject { message in ... }

SocketView

SwiftUI compatibility is key. It could look something like this:

var body: some View {
    SocketView(Message.self, Socket { ... }) { messages in
        List(messages) { message in
            Text(message.sender)
                .font(.caption)
            Text(message.body)
        }
    }
}

It gives you an array of the response type. The example above shows Codable support.

Question: Pagination

I'm using the RickAndMorty API alongside Request just fine here. The API is limited to 20 items per request. The data includes the page count, next url and previous url. I attempted to use RequestChain but I can't seem to figure out the correct way to handle the Data type. The end goal is to load all characters from the API using Request in a simple List. I've only used RequestView and AnyRequest and not sure if I can do what I'm trying using AnyRequest or even RequestChain/RequestGroup, been stuck on this for days now.

data struct

struct RickAndMorty: Codable {
    let info: Info
    let results: [Result]
}

struct Info: Codable {
    let pages: Int /// number of pages 34
    let next: String? /// next url string
    let prev: String? /// previous url string
}

Failed chain request

RequestChain {
    Request.chained { (data, err) in
        Url("https://rickandmortyapi.com/api/character/")
        Method(.get)
    }
    Request.chained { (data, err) in
       let json = try? Json(data[0]!)
       return Url(json!["info"]["next"].string)
    }
}
.call { (data, errors) in
    let json = try? Json(data[0]!)
    print(json!)
}

Merge two Url with + operator

I would like to add two URL to create a new one, for example:

Url("https://example.com/api/v1") + Url("/settings")

But, I believe that we can add one Url with a string too like that:

func + (_ url: Url, _ complementary: String) -> Url { Url("\(url.value ?? "")\(complementary)") }

Can't set request body

I followed the example in Readme but it always show error Type 'TestTest.Body' (aka 'some View') has no member 'init'.

XCode 11.4.1
IOS 13.4

Test Code

import SwiftUI
import Request

struct TestTest : View {
    @State var myData: String = "dono"
    let myToken = "12345"
    
    var body: some View {
    NavigationView {        

        VStack {
            Text(self.myData)
            
            Button(action: {
                Request {
                    Url("https://myurl.com/")
                    Method(.post)
                    Header.ContentType(.json)
                    Header.Any(key: "accessToken", value: self.myToken)
                    
                    Body(Json([
                        "data": "abcd"
                    ]).stringified)
                }
                .onString { data in
                    self.myData = data
                }
                .onError { error in
                    print(error)
                }
                .call()
                
            }
            ) {
                Text("update")
            }
        }
        .navigationBarTitle(Text("Todos"))
        }
    }
}

struct TestTest_Previews: PreviewProvider {
    static var previews: some View {
        TestTest()
    }
}

RequestChain nil data

I'm using RequestChain and it seemed to be working just fine. Now I'm receiving nil data when checking the errors. The URL is valid because I'm getting correct data from other chain requests in the chain. I'm seeing a strange error in Xcode output w_protocol_get_quic_image_block_invoke dlopen libquic failed.

Even removing the working chain requests to see if maybe I was sending too many requests at once didn't solve the issue, still nil data when checking with two requests in the chain. The API is working correctly, printed the URL and verified the data is valid.

func chainRequest() {
    RequestChain {
        Request.chained { (data, err) in
            Url("VALID_URL_AUTH")
            Method(.post)
            Query(["user": "USER_NAME", "password": "PASSWORD"])
            Header.UserAgent(.firefoxMac)
        }
        Request.chained { (data, err) in
            let json = try? Json(data[0]!)
            Url("VALID_API_URL")
            Header.Authorization(.bearer(json!["TOKEN"].string))
            Query(["KEY": "VALUE"])
            Method(.get)
            Header.UserAgent(.firefoxMac)
        }
    }
    .call { (data, errors) in
        print("\(String(describing:errors))")
    }
}

The 'Body' confilct

Dear carson-katri:

A XCode compile error occored while I added Request 'Body' :

Request { Url(createOrder) Method(.post) Header.ContentType(.json) Body(Json(data).stringified) //Type 'MyCustomSwiftUIView.Body' (aka 'some View') has no member 'init' }

How to fix it? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.