Apollo Automatic persisted queries #611
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #566
This PR implements Automatic persisted queries by Apollo:
PERSISTED_QUERY_NOT_SUPPORTED
code to avoid Apollo clients from trying to use persisted queriesThis diagram shows the process:
Essentially, whenever an Apollo client with enabled APQ attempts to execute a query, these are the steps taken:
query { field }
needs to be executed, it doeshash('sha256', 'query { field }')
and sends the resulting hash to the server:/graphql?hash=7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8
CachePersistedQueryLoader
. It checks if there's a7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8
entry in cache.extensions.code = 'PERSISTED_QUERY_NOT_FOUND'
. That tells Apollo clients that persisted queries are supported and it should go to the next step/graphql?hash=7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8&query=query { field }
7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8
matches the provided query usinghash('sha256', 'query { field }') === $hash
. If so, the server safely knows that this hash7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8
will always correspond to queryquery { field }
. It will write it to the cache:cache->set('7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8', 'query { field }')
. Afterwards, the request is processed normally, as if the client sent just thequery { field }
in the first place.query { field }
, they'll also first try executing it with just the hash:/graphql?hash=7b82cd908482825da2a4381cdda62a1384faa0c1b4c248e086aa44aa59fb9cd8
/graphql?query=query { field }
The reason authentication (or any other variables or headers) doesn't matter here is that only the string
query { field }
is cached. If two different clients try to use the same persisted query, both requests will still go through the full parsing, validation and execution process and may yield different responses.Hope that clears it up.