nrc / graphql

A Rust GraphQL server framework
Apache License 2.0
237 stars 12 forks source link

Client? #23

Open nrc opened 6 years ago

nrc commented 6 years ago

Is it worth writing a Rust GraphQL client? Should it be a separate project or part of this one?

mgattozzi commented 6 years ago

Currently Rust has no client libraries for GraphQL. There's juniper but it's also server only. It would be great if there was a client library. It'd be nice to autogenerate schema code like Diesel does by contacting the remote server but also just specifying the schema of the website out and generating the proper code to make requests would be really nice.

I know I'll need something like this for github-rs and I even started a proof of concept in there called github-gql-rs but the code and client api is really unergonomic and lacking.

There's a need for client libraries but no one has done it and filling that space would be a much needed feature if possible.

scrogson commented 6 years ago

I'm particularly interested in the ability to do schema-stitching similar to what's outlined here: https://dev-blog.apollodata.com/graphql-tools-a-simpler-way-to-create-graphql-apis-eadf018f3766

Something like this:

let schema_a = infer_remote_schema!("https://a.example.com/graphql", ...);
let schema_b = infer_remote_schema!("https://b.example.com/graphql", ...);
let schema = merge_schemas([schema_a, schema_b], ...);
mathstuf commented 6 years ago

Inferring remote schemas is going to break reproducible builds. It could also break API compatibility easily. I'd rather there be a "here's a schema we committed to the repository" for input.

scrogson commented 6 years ago

@mathstuf so maybe something more like diesel print-schema?

mathstuf commented 6 years ago

Maybe? I'm not familiar with diesel, but it looks like something in the right direction. Is there anything stopping it from being as simple as something like:

let schema = infer_schema!(include_bytes!("schemas/github.gql"));
mgattozzi commented 6 years ago

Diesel connects to the database then figures out everything it needs to generate the code then does it. infer_schema! does this at compile time while diesel print-schema does it at that point in time and generates the .rs files to be used.

I get wanting to have reproducible builds, but also on the other hand the server is going to likely be far more up to date than the package using it. I think the both options should be there to let the user choose how they want to go about it, while of course documenting the footguns of doing so.

mathstuf commented 6 years ago

The reproducible builds thing is just the first that came to my mind. I'm more worried about API stability. SQL schemas may be fine since they're usually only applicable for end-applications, but graphql will usually be used via libraries where stability is important.

mgattozzi commented 6 years ago

Unfortunately the GraphQL schema can change constantly and because it's not like a traditional REST API it's not versioned for stability. GraphQL says, "Here's the schema I support" via introspection. Now I'd hope the maintainer of that schema doesn't do anything crazy and keeps it relatively consistent like a SQL database, but I found within like a week or two of implementing GraphQL for GitHub it was changing a few things often. Mostly I think because it was newish. Keeping track of all the changes was frankly exhausting. I think over time as the technology matures schema maintainers will find a better way to maintain it without breaking everything, but I don't think GraphQL solves the problem it purports to with versioning and stability. I think it does help make smaller more focused requests though unlike a REST API.

That's why I do think that this should be an opt-in thing though. You either can print the schema out or do infer_schema!() and let the library maintainer for that API choose. One places a bigger cost on the maintainer (printing out the schema and accomodating fixes constantly), the other the consumer (oh the schema changed need to fix my code).

There might also be non library users. For instance despite hubcaps and github-rs (libraries for github in rust) existing I still see people code up hyper to do the requests. In this case I'd see infer_schema!() being used more likely. In the case of the library probably print schema. There's arguments for both with tradeoffs. I'm usually of the opinion of letting the end user choose how to use it and clearly letting them know the risks!

davidB commented 6 years ago

One of the main goal of graphql is to let client request only what he need, not all fields,... Then on server side, we can have metrics about usage of fields, add fields,...

If clients start to request every fields, you break this assumption, metrics and also can get slower response if some useless fields are requested and if those fields require additional computation/request on server side.

mathstuf commented 6 years ago

Could a Rust macro be written which does the equivalent of the NewRequest method described here?

mathstuf commented 6 years ago

One thing that would be useful for extracting from schema endpoints would be structures for use in queries. For building actual queries, macros would be best.

mathstuf commented 6 years ago

quicktype now has Rust support.

mathstuf commented 5 years ago

There is now graphql-client which is working really well for me.

mathstuf commented 5 years ago

because it's not like a traditional REST API it's not versioned for stability.

It's not explicitly versioned, but it does support deprecation of fields. This is way better than REST which can't really do that well. New fields are easy: clients which know about them can just request them. It being typed is also way better than REST and casting JSON objects with a hope and a prayer (or gobs of error checking).

In any case, I'd expect GitHub to get versioning more correct than many other GraphQL deployments.