New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Networktransport idea #6
Conversation
Thanks for bringing this up! I like the idea of making NetworkTransport more flexible, but before getting into specific designs, maybe we can look at the use cases we want to support first. Do you have any specific requirements in mind when you mention using the client with your own service/infrastructure? The reason for making NetworkTransport responsible for the parsing and error handling is that there are quite a few possible extension points when going from a GraphQL request to response, and because we don't know what those are yet, I lumped all of them together in one high level protocol. I deliberately defined NetworkTransport at the level of GraphQL operations because I wanted it to be able to perform GraphQL specific processing, and there can be considerable flexibility there. No transportation mechanism for GraphQL is defined in the spec, although fortunately there is a consensus around simple usage based on what I'd also prefer NetworkTransport to not be limited to HTTP. To support subscriptions, you would use WebSockets for instance, and you may want to send regular requests over that same connection instead of opening a separate HTTP connection for that. I haven't thought about this in detail, so these are just some first thoughts. Maybe we can identify some useful extension points and take it from there. |
Ok, I understand that. But a NetworkTransport should only do networking. I would recommend to put all your mentioned GraphQL logic into the client. After this reloacting the code I would try to separate the client in different pieces e.g parsing, loading, etc. All these pieces could be interchangeable. When I find time I try to model some interfaces |
I agree it makes sense to move some behavior around and split extension points up in different protocols, but I don't agree NetworkTransport has to be independent of GraphQL. One way of looking at this is that NetworkTransport represents what a GraphQL client requires from a network transport, rather than some general purpose networking layer. This is similar to the way Apollo Client and Relay approach this. You can plug in in any transport, as long as it allows you to send operations, and it can do transport-specific processing if needed (like batching, or even using an alternative serialization mechanism). |
We're currently using Apollo iOS with our own network stack & caching layer because we have other HTTP services in the app and want to centralize the networking aspect. I agree with @lightsprint09 on the architectural changes clearly separating the GraphQL layer from the network layer. As a framework consumer, I only want to use Apollo to serialize and deserialize GraphQL requests & responses to & from raw |
@MrAlek @lightsprint09: I'm happy to continue this conversation and see how we can make the framework more flexible. Most importantly, I'd like to better understand where the current design falls short, especially since we're starting to think about adding more network-level features like authentication, query batching and persisted queries. A WebSocket-based transport for subscriptions (and potentially all operations) is also on the roadmap. Right now, public protocol NetworkTransport {
func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (GraphQLResponse<Operation>?, Error?) -> Void) -> Cancellable
}
Most of the code in What do you feel is missing from the current design, and how do you suggest we should improve it? |
@martijnwalraven Me and @fwal (#46) are working on the same project and for us, even the In our implementation, we don't use The things you have on the roadmap for the network side of things in the client are great but there should still be an easy way to opt-out and just use the core serialization/deserialization of GraphQL operations for easier integration in existing apps. Example of our usage: static func request<O: GraphQLOperation>(_ operation: O, authenticationLevel: APIAuthenticationLevel, url: URL) throws -> HTTPRequest<O.Data> {
let map: GraphQLMap = ["query": type(of: operation).queryDocument, "variables": operation.variables]
let data = try JSONSerialization.data(withJSONObject: map.jsonValue, options: [])
let body = HTTPBody(data: data, contentType: .json)
return HTTPRequest<O.Data>(
url: url,
method: .post,
body: body,
authenticationLevel: authenticationLevel,
responseTransformer: { response in
// Error handling & response transformation using GraphQLResponse
}
}
} |
@MrAlek @fwal: I think it would be better in the longer term if we could make the interfaces flexible enough to allow for your use cases. Opting-out of using So I'm definitely open to suggestions if you feel there is anything missing in the API that blocks you from only using the library for serialization/deserialization, but I'd also like to better understand what restrictions you see that keep you from using it through the public API.
I'm not sure what you mean by this. Since
What keeps you from doing this within the |
This pull request contains two significant changes.
1. Changes the NetworkTransport to a real NetworkTransport.
NetworkTransport should not do parsing or handling domain specific errors. It only hits the network and returns with you requested data. It should not know anything about GraphQL at all.
2. Users of the API should be able build their own service.
All they need is a function to create an URLRequest from an operation with a given baseURL and a function which parses a JSON root object (or NSData) back to a GraphQLResult.
Those 2 described ideas can be helpful when the user of your API wants to use his own infrastructure.