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

Add skipValidation option. #839

Merged
merged 3 commits into from
Jul 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All of the packages in the `apollo-server` repo are released with the same versi

### vNEXT

* Add skipValidation option [PR #839](https://github.com/apollographql/apollo-server/pull/839)
* `apollo-server-module-graphiql`: adds an option to the constructor to disable url rewriting when editing a query [PR #1047](https://github.com/apollographql/apollo-server/pull/1047)
* Upgrade `subscription-transport-ws` to 0.9.9 for Graphiql

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ Apollo Server can be configured with an options object with the following fields
* **context**: the context value passed to resolvers during GraphQL execution
* **rootValue**: the value passed to the first resolve function
* **formatError**: a function to apply to every error before sending the response to clients
* **skipValidation**: skip query validation (increase performance, use carefully, only with whitelisting)
* **validationRules**: additional GraphQL validation rules to be applied to client-specified queries
* **formatParams**: a function applied for each query in a batch to format parameters before execution
* **formatResponse**: a function applied to each response after execution
Expand All @@ -228,6 +229,7 @@ All options except for `schema` are optional.
### Whitelisting

The `formatParams` function can be used in combination with the `OperationStore` to enable whitelisting.
In this case query parsing and validation will be called only once when saving to store.

```js
const store = new OperationStore(Schema);
Expand All @@ -236,6 +238,7 @@ graphqlOptions = {
schema: Schema,
formatParams(params) {
params['query'] = store.get(params.operationName);
params['skipValidation'] = true;
return params;
},
};
Expand Down
25 changes: 14 additions & 11 deletions packages/apollo-server-core/src/runQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface QueryOptions {
debug?: boolean;
tracing?: boolean;
cacheControl?: boolean | CacheControlExtensionOptions;
skipValidation?: boolean;
}

export function runQuery(options: QueryOptions): Promise<GraphQLResponse> {
Expand Down Expand Up @@ -171,17 +172,19 @@ function doRunQuery(options: QueryOptions): Promise<GraphQLResponse> {
documentAST = options.query as DocumentNode;
}

let rules = specifiedRules;
if (options.validationRules) {
rules = rules.concat(options.validationRules);
}
logFunction({ action: LogAction.validation, step: LogStep.start });
const validationErrors = validate(options.schema, documentAST, rules);
logFunction({ action: LogAction.validation, step: LogStep.end });
if (validationErrors.length) {
return Promise.resolve({
errors: format(validationErrors, options.formatError),
});
if (options.skipValidation !== true) {
let rules = specifiedRules;
if (options.validationRules) {
rules = rules.concat(options.validationRules);
}
logFunction({ action: LogAction.validation, step: LogStep.start });
const validationErrors = validate(options.schema, documentAST, rules);
logFunction({ action: LogAction.validation, step: LogStep.end });
if (validationErrors.length) {
return Promise.resolve({
errors: format(validationErrors, options.formatError),
});
}
}

if (extensionStack) {
Expand Down
33 changes: 33 additions & 0 deletions packages/apollo-server-integration-testsuite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const request = require('supertest');
import { GraphQLOptions } from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
import { OperationStore } from 'apollo-server-module-operation-store';
import { LogAction } from '../../apollo-server-core/dist';

const personType = new GraphQLObjectType({
name: 'PersonType',
Expand Down Expand Up @@ -1054,6 +1055,38 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => {
expect(res.body).to.deep.equal(expected);
});
});

it('do not validate if query is already an AST', async () => {
const store = new OperationStore(schema);
let validationCalled = false;
store.put('query testquery{ testString }');
app = await createApp({
graphqlOptions: {
schema,
formatParams(params) {
params['query'] = store.get(params.operationName);
params['skipValidation'] = true;
return params;
},
logFunction: ({ action }) => {
if (action == LogAction.validation) {
validationCalled = true;
}
},
},
});
const req = request(app)
.post('/graphql')
.send({
operationName: 'testquery',
});
return req.then(res => {
return expect(
validationCalled,
'Validation should not be called if skipValidation option provided',
).to.equal(false);
});
});
});

describe('server setup', () => {
Expand Down