Skip to content
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

enhancement: support graphql-playground #717

Merged
merged 21 commits into from
Apr 7, 2023
Merged

Conversation

0xmovses
Copy link
Contributor

@0xmovses 0xmovses commented Mar 29, 2023

Closes #646

Changelog

• Adds the crates async-graphql and async-graphql-axum.
• Adds the new api route /playground/:namespace/:identifier.
• Adds new handler function for the above route gql_playground.
• Appends data field to query responses so that playground renders response correctly.
• Updates tests to assert against the new response.
• Updates docs with new query.
• Updates the response type for handler function query_graph to GraphQLRequest.

Context

When initially testing querying in Postman, I found that our api would only accept a request of raw string. When I tried to use Postmans GraphQL testing request type, our server could not parse the request. I was able to reproduce this with the Playground, the playground was not functioning as it formats its requests to Graphql Request types. It was safe to assume that any GraphQL client would also not work.

I looked at some other repositories using graphql with the playground they implemented the async_graphql_axum::GraphQLRequest type. After doing this, our server was able to parse the queries from a graphQL client.

If we want prettier responses with the playground, we would have to update our response types to async_graphql_axum::GraphQLResponse, but I thought this was unnecessary for now.

Testing

  1. Run your local fuel-node cargo run --bin fuel-node
  2. Spin up the test indexer cargo run --bin fuel-indexer -- run --manifest packages/fuel-indexer-tests/components/indices/fuel-indexer-test/fuel_indexer_test.yaml
  3. In your browser go to http://localhost:29987/api/playground/fuel_indexer_test/index1 (you will see some error on initial render, ignore it).
  4. In the GraphQL Playground run the query:
query { 
    block 
    { 
        id 
        height 
        timestamp 
        }
}

You should receive the response. (If this fails you may need to trigger an event via the web-api so that the DB has some data to query).

{
    "data": [
        {
            "height": 1,
            "id": 3919316288814604599,
            "timestamp": 1680799333
        },
        {
            "height": 2,
            "id": 3832952940330561849,
            "timestamp": 1680799423
        },
        {
            "height": 3,
            "id": 3977631069887424055,
            "timestamp": 1680799493
        },
        {
            "height": 1,
            "id": 4121747375410198369,
            "timestamp": 1680800681
        },
        {
            "height": 2,
            "id": 7378647927350505569,
            "timestamp": 1680800974
        },
        {
            "height": 1,
            "id": 4135211972506432054,
            "timestamp": 1680801051
        },
        {
            "height": 2,
            "id": 3702856512725070640,
            "timestamp": 1680801341
        },
        {
            "height": 1,
            "id": 3474306528200385894,
            "timestamp": 1680811403
        }
    ]
}

For more optional testing you can try deploying a second indexer and using that namespace and identifier to query through the playground, if you like.

@0xmovses 0xmovses marked this pull request as draft March 29, 2023 13:12
@0xmovses 0xmovses requested a review from deekerno March 31, 2023 13:53
@0xmovses 0xmovses marked this pull request as ready for review March 31, 2023 13:53
@0xmovses 0xmovses requested a review from ra0x3 March 31, 2023 16:51
@deekerno
Copy link
Contributor

@rvmelkonian Thanks for doing this! I'll be reviewing this after I finish up the GraphQL filtering implementation.

Regarding the bit about JSON and the formatting for the playground, I wonder if there's an internal option that we can adjust with the playground, as JSON is the most common serialization format for GraphQL and it seems weird that the formatting would be wrong in that way. Otherwise, we would need to make sure that we could go from async_graphql_axum::GraphQLResponse to a proper JSON response body for those who won't be using the playground.

@0xmovses
Copy link
Contributor Author

0xmovses commented Mar 31, 2023

@deekerno I agree it does seem weird. I think that GraphQLResponse.into_response() will result in a proper JSON response 🤔. But we may not need to use this type for now. Will look into it.

@ra0x3
Copy link
Contributor

ra0x3 commented Apr 2, 2023

@rvmelkonian

  • Thanks for this, looks simple enough.
  • My first thought (have not reviewed yet, will do that soon) is - since you've removed the Query data type in favor of GraphQLRequest does that change how we're supposed to make requests against the the GET - /api/graph/:namespace/:identifier route?
    • If no, great!
    • If so, we'd need to update all docs that reference grabbing GraphQL data - since the docs still reference submitting a POST with { query: {} params } as the request body

Copy link
Contributor

@deekerno deekerno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! I had to adjust your testing steps a bit (I ended up using the block explorer example so I didn't have to run a node), but querying works as one would expect. This will be great when filtering and pagination are added.

A few questions that I'd like you to investigate before I approve this, if you don't mind:

  • The HTTP 500 error is being caused by the playground firing an introspection query as soon as it starts. And it actually does it every two seconds until it finally backs off. I've tried setting "schema.polling.enable" to false as it states in the playground docs, but it doesn't work. I don't think we'll ever support introspection (or not for a long time, at least) and many deployments don't enable it in production. Can you see if you can get it disabled?
  • The odd coloring may be caused by the fact that we're technically not spec-compliant when it comes to the format of the response; see this section of the latest version of the spec. Successful responses should have their payloads set as the value to the "data" key. Would you mind investigating this as well? I'd imagine that's the problem for the formatting, and it would benefit users who use GraphQL clients.

@0xmovses
Copy link
Contributor Author

0xmovses commented Apr 7, 2023

@deekerno
• I've added the data field to our responses, playground now renders with the correct colours and formatting 👍
• I tried to also set "schema.polling.enable" to false, but I also found it seems to have no effect.

@ra0x3
• I've updated our docs with the new queries required. I think it's better that we no longer have to pass the old params field.

My first thought (have not reviewed yet, will do that soon) is - since you've removed the Query data type in favor of GraphQLRequest does that change how we're supposed to make requests against the the GET - /api/graph/:namespace/:identifier route

• Answer is yes.

NB

• One odd thing I noticed, is when I test the old raw query in Postman, I get an error, which is what I would expect. However in our tests, the test client is still accepting the old raw string query. It responds 200 with the new data field response. I didn't want to go in and alter our tests too drastically, but thought I would bring this up.

@0xmovses 0xmovses requested a review from deekerno April 7, 2023 10:53
Copy link
Contributor

@ra0x3 ra0x3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rvmelkonian

Functionally this works. Played around with it for a bit. Looks good.

Left a few comments regarding Rust stuff. After those changes will ✅

Edit: Actually, we will want to add some docs for this new functionality as well.

  • In the book, under the "GraphQL section" we will want to add a new sub-section "9.4 Playground"
    • It doesn't have to be a novel, but we just need to mention what the playground is, how it works, and how users can spin it up

packages/fuel-indexer-api-server/src/uses.rs Outdated Show resolved Hide resolved
.status(StatusCode::OK)
.header(http::header::CONTENT_TYPE, "text/html; charset=utf-8")
.body(Body::from(html))
.expect("Failed to build gql playground response.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convention: unwrap with ?

Suggested change
.expect("Failed to build gql playground response.")
?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to implement the From method on enums ApiError and HttpError in order to satisfy the compiler. This allows us to use ? here.

@0xmovses 0xmovses requested a review from ra0x3 April 7, 2023 19:56
Copy link
Contributor

@deekerno deekerno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is shaping up to pretty damn nice, if I do say so myself.

@deekerno deekerno merged commit a18047c into master Apr 7, 2023
@deekerno deekerno deleted the rich/646-graphql-playground branch April 7, 2023 20:48
@0xmovses 0xmovses mentioned this pull request Apr 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support graphql playground
3 participants