Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Simple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.

License

NotificationsYou must be signed in to change notification settings

graphql/graphql-http

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


Simple, pluggable, zero-dependency,GraphQL over HTTP spec compliant server, client and audit suite.

CIgraphql-http

Quickly check for compliance? Visitgraphql-http.com!

Want a full-featured server? See theservers section!

Need subscriptions? Trygraphql-ws orgraphql-sse instead!


Getting started

Install

yarn add graphql-http

Create a GraphQL schema

import{GraphQLSchema,GraphQLObjectType,GraphQLString}from'graphql';/** * Construct a GraphQL schema and define the necessary resolvers. * * type Query { *   hello: String * } */constschema=newGraphQLSchema({query:newGraphQLObjectType({name:'Query',fields:{hello:{type:GraphQLString,resolve:()=>'world',},},}),});

Start the server

Withhttp
importhttpfrom'http';import{createHandler}from'graphql-http/lib/use/http';import{schema}from'./previous-step';// Create the GraphQL over HTTP Node request handlerconsthandler=createHandler({ schema});// Create a HTTP server using the listener on `/graphql`constserver=http.createServer((req,res)=>{if(req.url.startsWith('/graphql')){handler(req,res);}else{res.writeHead(404).end();}});server.listen(4000);console.log('Listening to port 4000');
Withhttp2

Browsers might complain about self-signed SSL/TLS certificates.Help can be found on StackOverflow.

$ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj'/CN=localhost' \  -keyout localhost-privkey.pem -out localhost-cert.pem
importfsfrom'fs';importhttp2from'http2';import{createHandler}from'graphql-http/lib/use/http2';import{schema}from'./previous-step';// Create the GraphQL over HTTP Node request handlerconsthandler=createHandler({ schema});// Create a HTTP/2 server using the handler on `/graphql`constserver=http2.createSecureServer({key:fs.readFileSync('localhost-privkey.pem'),cert:fs.readFileSync('localhost-cert.pem'),},(req,res)=>{if(req.url.startsWith('/graphql')){handler(req,res);}else{res.writeHead(404).end();}},);server.listen(4000);console.log('Listening to port 4000');
importexpressfrom'express';// yarn add expressimport{createHandler}from'graphql-http/lib/use/express';import{schema}from'./previous-step';// Create an express instance serving all methods on `/graphql`// where the GraphQL over HTTP express request handler isconstapp=express();app.all('/graphql',createHandler({ schema}));app.listen({port:4000});console.log('Listening to port 4000');
importFastifyfrom'fastify';// yarn add fastifyimport{createHandler}from'graphql-http/lib/use/fastify';import{schema}from'./previous-step';// Create a fastify instance serving all methods on `/graphql`// where the GraphQL over HTTP fastify request handler isconstfastify=Fastify();fastify.all('/graphql',createHandler({ schema}));fastify.listen({port:4000});console.log('Listening to port 4000');
WithKoa
importKoafrom'koa';// yarn add koaimportmountfrom'koa-mount';// yarn add koa-mountimport{createHandler}from'graphql-http/lib/use/koa';import{schema}from'./previous-step';constapp=newKoa();app.use(mount('/graphql',createHandler({ schema})));app.listen({port:4000});console.log('Listening to port 4000');
importuWSfrom'uWebSockets.js';// yarn add uWebSockets.js@uNetworking/uWebSockets.js#<version>import{createHandler}from'graphql-http/lib/use/uWebSockets';import{schema}from'./previous-step';uWS.App().any('/graphql',createHandler({ schema})).listen(4000,()=>{console.log('Listening to port 4000');});
WithDeno
import{serve}from'https://deno.land/std@0.151.0/http/server.ts';import{createHandler}from'https://esm.sh/graphql-http/lib/use/fetch';import{schema}from'./previous-step';// Create the GraphQL over HTTP native fetch handlerconsthandler=createHandler({ schema});// Start serving on `/graphql` using the handlerawaitserve((req:Request)=>{const[path,_search]=req.url.split('?');if(path.endsWith('/graphql')){returnhandler(req);}else{returnnewResponse(null,{status:404});}},{port:4000,// Listening to port 4000},);
WithBun
import{createHandler}from'graphql-http/lib/use/fetch';// bun install graphql-httpimport{schema}from'./previous-step';// Create the GraphQL over HTTP native fetch handlerconsthandler=createHandler({ schema});// Start serving on `/graphql` using the handlerexportdefault{port:4000,// Listening to port 4000fetch(req){const[path,_search]=req.url.split('?');if(path.endsWith('/graphql')){returnhandler(req);}else{returnnewResponse(null,{status:404});}},};
import{createHandler}from'graphql-http/lib/use/@netlify/functions';// yarn add@netlify/functionsimport{schema}from'./previous-step';// Create the GraphQL over HTTP native fetch handlerexportconsthandler=createHandler({ schema});

Use the client

import{createClient}from'graphql-http';constclient=createClient({url:'http://localhost:4000/graphql',});(async()=>{letcancel=()=>{/* abort the request if it is in-flight */};constresult=awaitnewPromise((resolve,reject)=>{letresult;cancel=client.subscribe({query:'{ hello }',},{next:(data)=>(result=data),error:reject,complete:()=>resolve(result),},);});expect(result).toEqual({hello:'world'});})();

Thanks toruru, serving GraphiQL is as easy as running:

npx ruru -SP -p 4001 -e http://localhost:4000/graphql

Openhttp://localhost:4001 in the browser to use it.

Recipes

🔗 Client usage with Promise
import{ExecutionResult}from'graphql';import{createClient,RequestParams}from'graphql-http';import{getSession}from'./my-auth';constclient=createClient({url:'http://hey.there:4000/graphql',headers:async()=>{constsession=awaitgetSession();if(session){return{Authorization:`Bearer${session.token}`,};}},});functionexecute<Data,Extensions>(params:RequestParams,):[request:Promise<ExecutionResult<Data,Extensions>>,cancel:()=>void]{letcancel!:()=>void;constrequest=newPromise<ExecutionResult<Data,Extensions>>((resolve,reject)=>{letresult:ExecutionResult<Data,Extensions>;cancel=client.subscribe<Data,Extensions>(params,{next:(data)=>(result=data),error:reject,complete:()=>resolve(result),});},);return[request,cancel];}(async()=>{const[request,cancel]=execute({query:'{ hello }',});// just an example, not a real functiononUserLeavePage(()=>{cancel();});constresult=awaitrequest;expect(result).toBe({data:{hello:'world'}});})();
🔗 Client usage withObservable
import{Observable}from'relay-runtime';// orimport{Observable}from'@apollo/client/core';// orimport{Observable}from'rxjs';// orimportObservablefrom'zen-observable';// or any other lib which implements Observables as per the ECMAScript proposal: https://github.com/tc39/proposal-observableimport{createClient}from'graphql-http';import{getSession}from'./my-auth';constclient=createClient({url:'http://graphql.loves:4000/observables',headers:async()=>{constsession=awaitgetSession();if(session){return{Authorization:`Bearer${session.token}`,};}},});constobservable=newObservable((observer)=>client.subscribe({query:'{ hello }'},observer),);constsubscription=observable.subscribe({next:(result)=>{expect(result).toBe({data:{hello:'world'}});},});// unsubscribe will cancel the request if it is pendingsubscription.unsubscribe();
🔗 Client usage withRelay
import{GraphQLError}from'graphql';import{Network,Observable,RequestParameters,Variables,}from'relay-runtime';import{createClient}from'graphql-http';import{getSession}from'./my-auth';constclient=createClient({url:'http://i.love:4000/graphql',headers:async()=>{constsession=awaitgetSession();if(session){return{Authorization:`Bearer${session.token}`,};}},});functionfetch(operation:RequestParameters,variables:Variables){returnObservable.create((sink)=>{if(!operation.text){returnsink.error(newError('Operation text cannot be empty'));}returnclient.subscribe({operationName:operation.name,query:operation.text,        variables,},sink,);});}exportconstnetwork=Network.create(fetch);
🔗 Client usage withApollo
import{ApolloLink,Operation,FetchResult,Observable,}from'@apollo/client/core';import{print,GraphQLError}from'graphql';import{createClient,ClientOptions,Client}from'graphql-http';import{getSession}from'./my-auth';classHTTPLinkextendsApolloLink{privateclient:Client;constructor(options:ClientOptions){super();this.client=createClient(options);}publicrequest(operation:Operation):Observable<FetchResult>{returnnewObservable((sink)=>{returnthis.client.subscribe<FetchResult>({ ...operation,query:print(operation.query)},{next:sink.next.bind(sink),complete:sink.complete.bind(sink),error:sink.error.bind(sink),},);});}}constlink=newHTTPLink({url:'http://where.is:4000/graphql',headers:async()=>{constsession=awaitgetSession();if(session){return{Authorization:`Bearer${session.token}`,};}},});
🔗 Client usage with request retries
import{createClient,NetworkError}from'graphql-http';constclient=createClient({url:'http://unstable.service:4000/graphql',shouldRetry:async(err:NetworkError,retries:number)=>{if(retries>3){// max 3 retries and then report service downreturnfalse;}// try again when service unavailable, could be temporaryif(err.response?.status===503){// wait one second (you can alternatively time the promise resolution to your preference)awaitnewPromise((resolve)=>setTimeout(resolve,1000));returntrue;}// otherwise report error immediatelyreturnfalse;},});
🔗 Client usage in browser
<!doctype html><html><head><metacharset="utf-8"/><title>GraphQL over HTTP</title><scripttype="text/javascript"src="https://unpkg.com/graphql-http/umd/graphql-http.min.js"></script></head><body><scripttype="text/javascript">constclient=graphqlHttp.createClient({url:'http://umdfor.the:4000/win/graphql',});// consider other recipes for usage inspiration</script></body></html>
🔗 Client usage in Node
constfetch=require('node-fetch');// yarn add node-fetchconst{ AbortController}=require('node-abort-controller');// (node < v15) yarn add node-abort-controllerconst{ createClient}=require('graphql-http');constclient=createClient({url:'http://no.browser:4000/graphql',fetchFn:fetch,abortControllerImpl:AbortController,// node < v15});// consider other recipes for usage inspiration
🔗 Client usage in Deno
import{createClient}from'https://esm.sh/graphql-http';constclient=createClient({url:'http://deno.earth:4000/graphql',});// consider other recipes for usage inspiration
🔗 Client usage in Bun
import{createClient}from'graphql-http';// bun install graphql-httpconstclient=createClient({url:'http://bun.bread:4000/graphql',});// consider other recipes for usage inspiration
🔗 Server handler migration fromexpress-graphql
import express from 'express';import { schema } from './my-graphql-schema';-import { graphqlHTTP } from 'express-graphql';+import { createHandler } from 'graphql-http/lib/use/express';const app = express();app.use(  '/graphql',-  graphqlHTTP({ schema }),+  createHandler({ schema }),);app.listen(4000);
🔗 Server handler usage with authentication

Authenticate the user withingraphql-http during GraphQL execution context assembly. This is a approach is less safe compared to early authentication (see early authentication in Node) because some GraphQL preparations or operations are executed even if the user is not unauthorized.

import{createHandler}from'graphql-http';import{schema,getUserFromCookies,getUserFromAuthorizationHeader,}from'./my-graphql';consthandler=createHandler({  schema,context:async(req)=>{// process token, authenticate user and attach it to your graphql contextconstuserId=awaitgetUserFromCookies(req.headers.cookie);// orconstuserId=awaitgetUserFromAuthorizationHeader(req.headers.authorization,);// respond with 401 if the user was not authenticatedif(!userId){return[null,{status:401,statusText:'Unauthorized'}];}// otherwise attach the user to the graphql contextreturn{ userId};},});
🔗 Server handler usage with custom context value
import{createHandler}from'graphql-http';import{schema,getDynamicContext}from'./my-graphql';consthandler=createHandler({  schema,context:async(req,args)=>{returngetDynamicContext(req,args);},// or static context by supplying the value directly});
🔗 Server handler usage with custom execution arguments
import{parse}from'graphql';import{createHandler}from'graphql-http';import{getSchemaForRequest,myValidationRules}from'./my-graphql';consthandler=createHandler({onSubscribe:async(req,params)=>{constschema=awaitgetSchemaForRequest(req);constargs={      schema,operationName:params.operationName,document:parse(params.query),variableValues:params.variables,};returnargs;},});
🔗 Server handler usage in Node with early authentication (recommended)

Authenticate the user early, before reachinggraphql-http. This is the recommended approach because no GraphQL preparations or operations are executed if the user is not authorized.

import{createHandler}from'graphql-http';import{schema,getUserFromCookies,getUserFromAuthorizationHeader,}from'./my-graphql';consthandler=createHandler({  schema,context:async(req)=>{// user is authenticated early (see below), simply attach it to the graphql contextreturn{userId:req.raw.userId};},});constserver=http.createServer(async(req,res)=>{if(!req.url.startsWith('/graphql')){returnres.writeHead(404).end();}try{// process token, authenticate user and attach it to the requestreq.userId=awaitgetUserFromCookies(req.headers.cookie);// orreq.userId=awaitgetUserFromAuthorizationHeader(req.headers.authorization,);// respond with 401 if the user was not authenticatedif(!req.userId){returnres.writeHead(401,'Unauthorized').end();}const[body,init]=awaithandler({url:req.url,method:req.method,headers:req.headers,body:()=>newPromise((resolve)=>{letbody='';req.on('data',(chunk)=>(body+=chunk));req.on('end',()=>resolve(body));}),raw:req,});res.writeHead(init.status,init.statusText,init.headers).end(body);}catch(err){res.writeHead(500).end(err.message);}});server.listen(4000);console.log('Listening to port 4000');
🔗 Server handler usage withgraphql-upload andhttp
importhttpfrom'http';import{createHandler}from'graphql-http/lib/use/http';importprocessRequestfrom'graphql-upload/processRequest.mjs';// yarn add graphql-uploadimport{schema}from'./my-graphql';consthandler=createHandler({  schema,asyncparseRequestParams(req){constparams=awaitprocessRequest(req.raw,req.context.res);if(Array.isArray(params)){thrownewError('Batching is not supported');}return{      ...params,// variables must be an object as per the GraphQL over HTTP specvariables:Object(params.variables),};},});constserver=http.createServer((req,res)=>{if(req.url.startsWith('/graphql')){handler(req,res);}else{res.writeHead(404).end();}});server.listen(4000);console.log('Listening to port 4000');
🔗 Server handler usage withgraphql-upload andexpress
importexpressfrom'express';// yarn add expressimport{createHandler}from'graphql-http/lib/use/express';importprocessRequestfrom'graphql-upload/processRequest.mjs';// yarn add graphql-uploadimport{schema}from'./my-graphql';constapp=express();app.all('/graphql',createHandler({    schema,asyncparseRequestParams(req){constparams=awaitprocessRequest(req.raw,req.context.res);if(Array.isArray(params)){thrownewError('Batching is not supported');}return{        ...params,// variables must be an object as per the GraphQL over HTTP specvariables:Object(params.variables),};},}),);app.listen({port:4000});console.log('Listening to port 4000');
🔗 Audit for servers usage inJest environment
import{fetch}from'@whatwg-node/fetch';import{serverAudits}from'graphql-http';for(constauditofserverAudits({url:'http://localhost:4000/graphql',fetchFn:fetch,})){test(audit.name,async()=>{constresult=awaitaudit.fn();if(result.status==='error'){throwresult.reason;}if(result.status==='warn'){console.warn(result.reason);// or throw if you want full compliance (warnings are not requirements)}// result.status === 'ok'});}
🔗 Audit for servers usage inDeno environment
import{serverAudits}from'npm:graphql-http';for(constauditofserverAudits({url:'http://localhost:4000/graphql',fetchFn:fetch,})){Deno.test(audit.name,async()=>{constresult=awaitaudit.fn();if(result.status==='error'){throwresult.reason;}if(result.status==='warn'){console.warn(result.reason);// or throw if you want full compliance (warnings are not requirements)}// Avoid leaking resourcesif('body'inresult&&result.bodyinstanceofReadableStream){awaitresult.body.cancel();}});}

Put the above contents in a file and run it withdeno test --allow-net.

This is the officialGraphQL over HTTP spec reference implementation and as such follows the specification strictly without any additional features (like playgrounds or GUIs, file uploads, @stream/@defer directives and subscriptions).

Having said this, graphql-http is mostly aimed for library authors and simple server setups, where the requirements are exact to what the aforementioned spec offers.

If you want a feature-full server with bleeding edge technologies, you're recommended to use one of the following servers.

Their compliance with theGraphQL over HTTP spec is checked automatically and updated regularly.

NameAudit
apollo-server✅ Compliant
deno✅ Compliant
graph-client✅ Compliant
graphql-helix✅ Compliant
graphql-yoga✅ Compliant
hotchocolate✅ Compliant
lighthouse✅ Compliant
pioneer✅ Compliant
postgraphile✅ Compliant

Check thedocs folder out forTypeDoc generated documentation.

Inspect audits of other implementations in theimplementations folder.Adding your implementation is very welcome,see how!

Want to help?

File a bug, contribute with code, or improve documentation?Read more in CONTRIBUTING.md.

If your company benefits from GraphQL and you would like to provide essential financial support for the systems and people that power our community, please also consider membership in theGraphQL Foundation.


[8]ページ先頭

©2009-2025 Movatter.jp