wvteijlingen / Spine

A Swift library for working with JSON:API APIs. It supports mapping to custom model classes, fetching, advanced querying, linking and persisting.
MIT License
264 stars 109 forks source link

Possible to make query with custom URL and inferred response type? #120

Closed stephensilber closed 7 years ago

stephensilber commented 7 years ago

The API I'm working with has a route ("http://api.com/users/login") that expects a token to be set in the header and returns a User object. The problem is Spine thinks that the user's ID is "login". Is there a way to do this with a Query object?

Expected behavior: --> Request http://api.com/users/login with header token "x-token" set <-- Return User object

wvteijlingen commented 7 years ago

Query has an initialiser that takes a URL path: init(resourceType: T.Type, path: String). Headers are a little more work though. HTTPClient supports headers, but only for all requests. If you want a specific header for just one request you'd have to subclass it and override the buildRequest method to add your own header if the URL matches.

stephensilber commented 7 years ago

This token would persist for the rest of calls made by Spine anyway, so that's not an issue.

I think the problem is that I want to build a custom "query" that's a POST method but it doesn't look like that is supported. I get a bad response due to the fact that the query is a GET method.

request:

    func signIn(twitterToken: String) -> PromiseKit.Promise<Void> {
        self.setToken(twitterToken, key: "token")
        self.client.setHeader("x-twitter-token", to: twitterToken)

        return PromiseKit.Promise { fulfill, reject in
            let query = Query(resourceType: User.self, path: "/api/users/login")//Query(resourceType: User.self)
            spine.find(query).onSuccess { (resource, meta, jsonapi) in
                guard let  user = resource.resources.first as? User else { return reject(SpineManagerError.UserNotSet) }
                self.user = user
                return fulfill()
            }.onFailure { error in
                self.clearTokens()
                return reject(error)
            }
        }
    }

reponse:

Warning  - 404: http://api.com/api/users/login – (127 bytes)
Debug    - {"errors":[{"status":404,"code":"resource_not_found","title":"Users Not Found","detail":"Users with id login was not found."}]}
stephensilber commented 7 years ago

I was able to work around this by building a custom HTTPClient like you said, and override buildRequest. I would love a solution that doesn't hard code routes if it's available, but this works for now. Thanks for the suggestion!