Wrapping REST API with GraphQL / just using GraphQL - rest

I am working a project where I will be integrating GraphQL to a backend Express server. Currently, the server's structure is much like a MVC pattern structure.
Controllers folder
functions to query data from a MySQL database and return it.
ex: file named Car.js and in there are functions such as getAllCars() and getCar(id)
Routers folder
endpoints that call the functions in the controllers and returns it to caller
ex: endpoint GET /cars that will call getAllCars() and return it
I want to wrap GraphQL on top of this and was wondering what if the best way to do this. As far as I know, each GraphQL type has fields and resolvers and the resolver is the one that will get the data (please correct me if I'm wrong).
So I guess my question is...
If I want to wrap GraphQL on this, in the resolver, do I call the endpoint that will fetch me the data?
If I have a controllers folder that is already handling the data access/modification in the db, can I simply just call the controller function in the resolver and don't necessarily 'need any endpoints'?
I hope this makes sense, I am still very new to GraphQL and am very excited to work with it.
Thank you!

Please find my answers below
If I want to wrap GraphQL on this, in the resolver, do I call the endpoint that will fetch me the data?
The GraphQL should always be served from a single end point. It is the query that changes but the end point will always be the same.
If I have a controllers folder that is already handling the data access/modification in the db, can I simply just call the controller function in the resolver and don't necessarily 'need any endpoints'?
This is debatable. It is a good practice to always separate out the handling the data access/ modification outside the controller like in a service layer.

Related

NestJs #ResolveField alternative in REST

In NestJs when we use it in combination with GraphQl, we can call #ResolveField decorator, do we have some alternatives when we use REST?
I have worked once with GraphQl and used that decorator, and now im working with rest, and want to know do we have something simillar in NestJs without Graph.
REST does not have the idea of being able to optionally add extra fields to the response just by adding a sub field to the response. It's not a query language like GraphQL is. You would need to either add in a query parameter that allows the client to say "fetch extra data" or just return the extra data by default and let the client ignore it if it is not wanted

How can my Apollo GraphQL resolver 'lookahead' to children without losing the benefits of a traditional resolver structure?

I'm working on a GraphQL API which sits in front of a REST service. This REST service is a single endpoint with a lot of complex parameters - rather than put all the parameters on a single GraphQL field, we've logically broken it down into a tree of GraphQL fields and types.
In particular, the bottom of this tree is somewhat dynamic and unbounded. All in, it looks something like this simplified schema:
type Query {
outer: OuterWrapper!
}
type OuterWrapper {
inner: InnerWrapper!
}
type InnerWrapper {
recurse(name: String = ""): RecursiveType!
}
type RecursiveType {
recurse(name: String = ""): [RecursiveType!]!
name: String!
}
Currently, we have just one Apollo resolver at the top of the tree (outer), and use the graphql-fields library to process the info parameter. Essentially, we're 'looking ahead' to the children - a popular pattern to optimise backend queries.
This works quite well for us - we map the child fields and parameters into a single REST request, and then map the response back into the correct structure.
However, it does have two limitations:
The graphql-fields response doesn't include the values of default parameters. If I wrote a proper recurse resolver, Apollo would pass in the schema default value for name if it wasn't in the query. I found an alternative library (graphql-parse-resolve-info) that I'm going to switch to, but that's not an Apollo solution, and...
If we throw an error, the path reflects that it occurred in the outer resolver, rather than further down the tree where it would be more accurate, and useful to the user.
Taken together, I'm concerned that I'm going to continue finding things that don't quite work using this kind of structure, and I'm thinking about how I could move away from it.
Is there a way I could incrementally build my single backend REST request using a traditional/fully specified resolver structure?
I could imagine the resolvers building up the query, and storing it in the context - the outer resolver would create the query, and subsequent resolvers would change it as they see fit. Then each resolver could return a promise that's waiting on the REST response. However, I can't see a good way to know when all my resolvers have been called (and made their changes), and thus to fire the REST request to the backend, or for each resolver to know where it sits in the query structure (and hence where to look for data in the REST response).
Is there another approach I haven't considered?
GraphQL's top-down way of executing requests doesn't really lend itself to resolvers building up a query that would be executed once all resolvers are ran. In part, this is because the parent field's resolver has to complete execution before any child field resolvers are called. After all, they need to be called with the value that the parent resolved to.
If you had multiple calls to your datasource, it might make sense to split them across different resolvers. If you only need to make a single call to your datasource, though, doing so at the top level and using "lookahead" is the best approach. graphql-parse-resolve-info is an excellent library to help with that.
The only improvement over what you're doing now might be to move most of the logic for transforming the REST response into the resolvers for some of your non-root fields. In this way, you can gradually transform the parent value passed to each resolver as the execution moves through each "level" of your query.

Routing incoming request

I am trying to create a simple API using Go that performs certain operations depending on the data provided.
I was planning to provide JSON data to this API and get details from it for further use.
Since I was trying to provide JSON data I created the routing using gorilla/mux as below:
router.HandleFunc("/msa/dom/perform-factory-reset?json={jsonData}", CallGet)
log.Fatal(http.ListenAndServe(":8080", router))
But while trying to hit the endpoint http://localhost:8080/msa/dom/perform-factory-reset?json={"vrf":"ds","ip":"45","mac":"452","method":"gfd"} I am getting 404 page not found error.
Hence I tried to change the implementation such that new routing is done as:
router.HandleFunc("/msa/dom/perform-factory-reset/json={jsonData}", CallGet)
This works absolutely fine and I am able to perform desired tasks. Could someone tell me why this is happening?
Is the router gorilla/mux? If so, you cannot add query parameters to path like that. You have to:
router.Path("/msa/dom/perform-factory-reset").
Queries("json","{jsonData}").HandlerFunc(CallGet)
If it is some other router, then you still probably have to register path without the query parameters, and then get the query parameter values in the handler from the request.

Using GraphQL strictly as a query language

I think that my problem is a common one, and I'm weighing the costs and benefits of GraphQL as a solution.
I work on a product whose data is stored by a monolithic CRUD-based REST API. We have components of our application expose a search interface for data, and of course need some kind of server-side support for making requests for that data. This could include sorting, filtering, choosing fields, etc. There are, of course, more traditional ways of providing these functions in a REST context, like query parameter add-ons for endpoints, but it would be cool to try out GraphQL in this context to build a foundation for expanding its use for querying a bit.
GraphQL exposes a really nice query language for searching on data, and ultimately allows me to tailor the language of search specifically to my domain. However, I'm not sure if there is a great way to leverage the IDL without managing a separate server altogether.
Take the following Java Jersey API Proof-of-Concept example:
#GET
#Path("/api/v1/search")
public Response search(QueryIDL query) throws IOException {
final SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeDefinitionRegistry = // load schema
RuntimeWiring runtimeWiring = // wire up data-fetching classes
SchemaGenerator schemaGenerator = new SchemaGenerator();
GraphQLSchema graphQLSchema =
schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);
GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();
ExecutionResult executionResult = build.execute(query.toString());
return Response.ok(executionResult.getData()).build();
}
I am just planning to take a request body into my Jersey server that looks exactly like the request that would be sent to a GraphQL server. I'm then leveraging some library support to interpret and execute the request for data.
Without really thinking too much about everything that could go wrong, it looks like a client would be able to use this API similar to the way they would use a GraphQL server, except that I don't need to necessarily manage a separate server just to facilitate my search requirements.
Does it seem valuable, or silly, to use the GraphQL IDL in an endpoint-based context like this?
Apart from not needing to rebuild the schema or the GraphQL instance on each request (there are cases where you may want to rebuild the GraphQL instance, but your case is not the one), this is pretty much the canonical way of using it.
It is rather uncommon to keep a separate server for GraphQL, and it usually gets introduced exactly the way you described - as just another endpoint next to your usual REST endpoints. So your usage is legit - not silly at all :)
Btw, I'm not sure what would QueryIDL be... the query is just a string. No need for a special class.

Exposing database query parameters via REST interface

I have the basics of a REST service done, with "standard" list and GET/POST/PUT/DELETE verbs implemented around my nouns.
However, the client base I'm working with also wants to have more powerful operations. I'm using Mongo DB on the back-end, and it'd be easy to expose an "update" operation. This page describes how Mongo can do updates.
It'd be easy to write a page that takes a couple of JSON/XML/whatever arguments for the "criteria" and the "objNew" parts of the Mongo update function. Maybe I make a page like http://myserver.com/collection/update that takes a POST (or PUT?) request, with a request body that contains that data. Scrub the input for malicious querying and to enforce security, and we're done. Piece of cake.
My question is: what's the "best" way to expose this in a RESTful manner? Obviously, the approach I described above isn't kosher because "update" isn't a noun. This sort of thing seems much more suitable for a SOAP/RPC method, but the rest of the service is already using REST over HTTP, and I don't want users to have to make two different types of calls.
Thoughts?
Typically, I would handle this as:
url/collection
url/collection/item
GET collection: Returns a representation of the collection resource
GET collection/item: Returns a representation of the item resource
(optional URI params for content-types: json, xml, txt, etc)
POST collection/: Creates a new item (if via XML, I use XSD to validate)
PUT collection/item: Update an existing item
DELETE collection/item: Delete an existing item
Does that help?
Since as you're aware it isn't a good fit for REST, you're just going to have to do your best and invent a standard to make it work. Mongo's update functionality is so far removed from REST, I'd actually allow PUTs on the collection. Ignore the parameters in my examples, I haven't thought too hard about them.
PUT collection?set={field:value}
PUT collection?pop={field:1}
Or:
PUT collection/pop?field=1