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

Fix Micro server handler #401

Merged
merged 4 commits into from
Jun 16, 2017
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
15 changes: 15 additions & 0 deletions packages/graphql-server-integration-testsuite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,5 +817,20 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => {
});
});
});

describe('server setup', () => {
it('throws error on 404 routes', () => {
app = createApp();

const query = {
query: '{ testString }',
};
const req = request(app)
.get(`/bogus-route?${querystring.stringify(query)}`);
return req.then((res) => {
expect(res.status).to.equal(404);
});
});
});
});
};
11 changes: 10 additions & 1 deletion packages/graphql-server-lambda/src/lambdaApollo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@ import 'mocha';
import * as url from 'url';

function createLambda(options: CreateAppOptions = {}) {
let handler,
let route,
handler,
callback,
event,
context;

options.graphqlOptions = options.graphqlOptions || { schema: Schema };
if (options.graphiqlOptions ) {
route = '/graphiql';
handler = graphiqlLambda( options.graphiqlOptions );
} else {
route = '/graphql';
handler = graphqlLambda( options.graphqlOptions );
}

return function(req, res) {
if (!req.url.startsWith(route)) {
res.statusCode = 404;
res.end();
return;
}

let body = '';
req.on('data', function (chunk) {
body += chunk;
Expand Down
23 changes: 23 additions & 0 deletions packages/graphql-server-micro/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# graphql-server-micro

This is the [Micro](https://github.com/zeit/micro) integration for the Apollo community GraphQL Server. [Read the docs.](http://dev.apollodata.com/tools/apollo-server/index.html)


## Example
```typescript
import { microGraphiql, microGraphql } from "graphql-server-micro";
import micro, { send } from "micro";
import { get, post, router } from "microrouter";
import schema from "./schema";

const graphqlHandler = microGraphql({ schema });
const graphiqlHandler = microGraphiql({ endpointURL: "/graphql" });

const server = micro(
router(
get("/graphql", graphqlHandler),
post("/graphql", graphqlHandler),
get("/graphiql", graphiqlHandler),
(req, res) => send(res, 404, "not found"),
),
);

server.listen(3000);
```
6 changes: 4 additions & 2 deletions packages/graphql-server-micro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@
},
"devDependencies": {
"graphql-server-integration-testsuite": "^0.8.4",
"micro": "^7.3.3"
"micro": "^7.3.3",
"microrouter": "^2.1.1"
},
"peerDependencies": {
"graphql": "^0.9.0 || ^0.10.1",
"micro": "^7.3.3"
},
"optionalDependencies": {
"@types/graphql": "^0.9.1"
"@types/graphql": "^0.9.1",
"@types/micro": "^7.3.0"
},
"typings": "dist/index.d.ts",
"typescript": {
Expand Down
39 changes: 31 additions & 8 deletions packages/graphql-server-micro/src/microApollo.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
import { microGraphql, microGraphiql } from './microApollo';
import 'mocha';

import * as micro from 'micro';
import testSuite, { schema as Schema, CreateAppOptions } from 'graphql-server-integration-testsuite';
import micro, { send } from 'micro';
import { router, get, post, put, patch, del, head, options as opts } from 'microrouter';
import testSuite, { schema, CreateAppOptions } from 'graphql-server-integration-testsuite';


function createApp(options: CreateAppOptions) {
if (options && options.graphiqlOptions ) {
return micro(microGraphiql( options.graphiqlOptions ));
} else {
const graphqlOptions = (options && options.graphqlOptions) || { schema: Schema };
return micro(microGraphql(graphqlOptions));
}
const graphqlOptions = (options && options.graphqlOptions) || { schema };
const graphiqlOptions = (options && options.graphiqlOptions) || { endpointURL: '/graphql' };

const graphqlHandler = microGraphql(graphqlOptions);
const graphiqlHandler = microGraphiql(graphiqlOptions);

return micro(
router(
get('/graphql', graphqlHandler),
post('/graphql', graphqlHandler),
put('/graphql', graphqlHandler),
patch('/graphql', graphqlHandler),
del('/graphql', graphqlHandler),
head('/graphql', graphqlHandler),
opts('/graphql', graphqlHandler),

get('/graphiql', graphiqlHandler),
post('/graphiql', graphiqlHandler),
put('/graphiql', graphiqlHandler),
patch('/graphiql', graphiqlHandler),
del('/graphiql', graphiqlHandler),
head('/graphiql', graphiqlHandler),
opts('/graphiql', graphiqlHandler),

(req, res) => send(res, 404, 'not found'),
),
);
}

describe('integration:Micro', () => {
Expand Down
43 changes: 22 additions & 21 deletions packages/graphql-server-micro/src/microApollo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { GraphQLOptions, HttpQueryError, runHttpQuery } from 'graphql-server-core';
import * as GraphiQL from 'graphql-server-module-graphiql';
import { json } from 'micro';
import { createError, json, RequestHandler } from 'micro';
import * as url from 'url';
import {IncomingMessage, ServerResponse} from 'http';

export interface MicroGraphQLOptionsFunction {
(req?: IncomingMessage): GraphQLOptions | Promise<GraphQLOptions>;
}

export function microGraphql(options: GraphQLOptions | MicroGraphQLOptionsFunction) {
export function microGraphql(options: GraphQLOptions | MicroGraphQLOptionsFunction): RequestHandler {
if (!options) {
throw new Error('Apollo Server requires options.');
}
Expand All @@ -29,33 +29,34 @@ export function microGraphql(options: GraphQLOptions | MicroGraphQLOptionsFuncti
query = url.parse(req.url, true).query;
}

runHttpQuery([req, res], {
method: req.method,
options: options,
query: query,
}).then((gqlResponse) => {
try {
const gqlResponse = await runHttpQuery([req, res], {
method: req.method,
options: options,
query: query,
});

res.setHeader('Content-Type', 'application/json');
res.write(gqlResponse);
res.end();
}, (error: HttpQueryError) => {
if ( 'HttpQueryError' !== error.name ) {
throw error;
return gqlResponse;
} catch (error) {
if ('HttpQueryError' === error.name) {
if (error.headers) {
Object.keys(error.headers).forEach((header) => {
res.setHeader(header, error.headers[header]);
});
}
}

if ( error.headers ) {
Object.keys(error.headers).forEach((header) => {
res.setHeader(header, error.headers[header]);
});
if (!error.statusCode) {
error.statusCode = 500;
}

res.statusCode = error.statusCode;
res.write(error.message);
res.end();
});
throw error;
}
};
}

export function microGraphiql(options: GraphiQL.GraphiQLData) {
export function microGraphiql(options: GraphiQL.GraphiQLData): RequestHandler {
return (req: IncomingMessage, res: ServerResponse) => {
const q = req.url && url.parse(req.url, true).query || {};
const query = q.query || '';
Expand Down