DEPRECATED
Apollo Client 2.0 no longer uses apollo-fetch
but apollo-link
instead. See https://www.apollographql.com/docs/react/2.0-migration.html for an example.
This module is deprecated and will not receive further updates.
apollo-fetch
apollo-fetch
is a lightweight client for GraphQL requests that supports middleware and afterware that modify requests and responses.
By default apollo-fetch
uses cross-fetch
, but you have the option of using a custom fetch function.
If you are interested in contributing, please read the documentation on repository structure and Contributor Guide.
Installation
npm install apollo-fetch --save
To use apollo-fetch
in a web browser or mobile app, you'll need a build system capable of loading NPM packages on the client.
Some common choices include Browserify, Webpack, and Meteor +1.3.
Usage
To create a fetch function capable of supporting middleware and afterware, use createApolloFetch
:
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const apolloFetch = createApolloFetch({ uri });
To execute the fetch function, call apolloFetch
directly in the following way:
apolloFetch({ query, variables, operationName }) //all apolloFetch arguments are optional
.then(result => {
const { data, errors, extensions } = result;
//GraphQL errors and extensions are optional
})
.catch(error => {
//respond to a network error
});
Middleware and Afterware
Middleware and Afterware are added with use
and useAfter
directly to apolloFetch
:
const apolloFetch = createApolloFetch();
const middleware = ({ request, options }, next) => { ... next(); };
const afterware = ({ response, options }, next) => { ... next(); };
apolloFetch.use(middleware);
apolloFetch.useAfter(afterware);
Middleware and Afterware can be chained together in any order:
const apolloFetch = createApolloFetch();
apolloFetch
.use(middleware1)
.use(middleware2)
.useAfter(afterware1)
.useAfter(afterware2)
.use(middleware3);
Custom Fetch
For mocking and other fetching behavior, you may pass a fetch into createApolloFetch
:
const customFetch = createFileFetch();
const apolloFetch = createApolloFetch({ customFetch });
Custom GraphQL to Fetch Translation
To modify how GraphQL requests are incorporated in the fetch options, you may pass a transformation function into createApolloFetch
.
apollo-fetch
exports constructDefaultOptions
to allow conditional creation of the fetch options.
These transformations can be useful for servers that have different formatting for batches or other extra capabilities.
//requestOrRequests: GraphQLRequest | GraphQLRequest[]
//options: RequestInit
const constructOptions = (requestOrRequests, options) => {
return {
...options,
body: JSON.stringify(requestOrRequests),
}
};
const apolloFetch = createApolloFetch({ constructOptions });
//simplified usage inside apolloFetch
fetch(uri, constructOptions(requestOrRequests, options)); //requestOrRequests and options are the results from middleware
Batched Requests
Batched requests are also supported by the fetch function returned by createApolloFetch
, please refer the batched request guide for a complete description.
Examples
Simple GraphQL Query
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const query = `
query CurrentUser {
currentUser {
login,
}
}
`
const apolloFetch = createApolloFetch({ uri });
apolloFetch({ query }).then(...).catch(...);
Simple GraphQL Mutation with Variables
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const query = `
mutation SubmitRepo ($repoFullName: String!) {
submitRepository (repoFullName: $repoFullName) {
id,
score,
}
}
`;
const variables = {
repoFullName: 'apollographql/apollo-fetch',
};
const apolloFetch = createApolloFetch({ uri });
apolloFetch({ query, variables }).then(...).catch(...);
Middleware
A GraphQL mutation with authentication middleware. Middleware has access to the GraphQL query and the options passed to fetch.
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const apolloFetch = createApolloFetch({ uri });
apolloFetch.use(({ request, options }, next) => {
if (!options.headers) {
options.headers = {}; // Create the headers object if needed.
}
options.headers['authorization'] = 'created token';
next();
});
apolloFetch(...).then(...).catch(...);
Afterware
Afterware to check the response status and logout on a 401. The afterware has access to the raw reponse always and parsed response when the data is proper JSON.
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const apolloFetch = createApolloFetch({ uri });
apolloFetch.useAfter(({ response }, next) => {
if (response.status === 401) {
logout();
}
next();
});
apolloFetch(...).then(...).catch(...);
Mocking a Fetch Call
This example uses a custom fetch to mock an unauthorized(401) request with a non-standard response body.
apollo-fetch
replaces the call to fetch
with customFetch
, which both follow the standard Fetch API.
const customFetch = () => new Promise((resolve, reject) => {
const init = {
status: 401,
statusText: 'Unauthorized',
};
const body = JSON.stringify({
data: {
user: null,
}
});
resolve(new Response(body, init));
}
const apolloFetch = createApolloFetch({ customFetch });
Error Handling
All responses are passed to the afterware regardless of the http status code.
Network errors, FetchError
, are thrown after the afterware is run and if no parsed response is received.
This example shows an afterware that can receive a 401 with an unparsable response and return a valid FetchResult
.
Currently all other status codes that have an uparsable response would throw an error.
This means if a server returns a parsable GraphQL result on a 403 for example, the result would be passed to then
without error.
Errors in Middleware and Afterware are propagated without modification.
import { createApolloFetch } from 'apollo-fetch';
const uri = 'http://api.githunt.com/graphql';
const apolloFetch = createApolloFetch({ uri });
apolloFetch.useAfter(({ response }, next) => {
//response.raw will be a non-null string
//response.parsed may be a FetchResult or undefined
if (response.status === 401 && !response.parsed) {
//set parsed response to valid FetchResult
response.parsed = {
data: { user: null },
};
}
next();
});
//Here catch() receives all responses with unparsable data
apolloFetch(...).then(...).catch(...);
Apollo Integration
apollo-fetch
is the first part of Apollo Client's future network stack.
If you would like to try it out today,
you may replace the network interface with the following:
import ApolloClient from 'apollo-client';
import { createApolloFetch } from 'apollo-fetch';
import { print } from 'graphql/language/printer';
const uri = 'http://api.githunt.com/graphql';
const apolloFetch = createApolloFetch({ uri });
const networkInterface = {
query: (req) => apolloFetch({...req, query: print(req.query)}),
};
const client = new ApolloClient({
networkInterface,
});
API
createApolloFetch
is a factory for ApolloFetch
, a fetch function with middleware and afterware capabilities.
Response
and RequestInit
follow the MDN standard fetch API.
createApolloFetch(options: FetchOptions): ApolloFetch
FetchOptions {
uri?: string;
customFetch?: (request: RequestInfo, init: RequestInit) => Promise<Response>;
constructOptions?: (requestOrRequests: GraphQLRequest | GraphQLRequest[], options: RequestInit) => RequestInit;
}
/*
* defaults:
* uri = '/graphql'
* customFetch = fetch from cross-fetch
* constructOptions = constructDefaultOptions(exported from apollo-fetch)
*/
ApolloFetch
, a fetch function with middleware, afterware, and batched request capabilities.
For information on batch usage, see the batched request documentation.
ApolloFetch {
(operation: GraphQLRequest): Promise<FetchResult>;
use: (middlewares: MiddlewareInterface) => ApolloFetch;
useAfter: (afterwares: AfterwareInterface) => ApolloFetch;
//Batched requests are described in the docs/batch.md
(operation: GraphQLRequest[]): Promise<FetchResult[]>;
batchUse: (middlewares: BatchMiddlewareInterface) => ApolloFetch;
batchUseAfter: (afterwares: BatchAfterwareInterface) => ApolloFetch;
}
GraphQLRequest
is the argument to an ApolloFetch
call.
query
is optional to support persistent queries based on only an operationName
.
GraphQLRequest {
query?: string;
variables?: object;
operationName?: string;
}
FetchResult
is the return value of an ApolloFetch
call
FetchResult {
data: any;
errors?: any;
extensions?: any;
}
Middleware used by ApolloFetch
MiddlewareInterface: (request: RequestAndOptions, next: Function) => void
RequestAndOptions {
request: GraphQLRequest;
options: RequestInit;
}
Afterware used by ApolloFetch
AfterwareInterface: (response: ResponseAndOptions, next: Function) => void
ResponseAndOptions {
response: ParsedResponse;
options: RequestInit;
}
ParsedResponse
adds raw
(the body from the .text()
call) to the fetch result, and parsed
(the parsed JSON from raw
) to the fetch's standard Response.
ParsedResponse extends Response {
raw: string;
parsed?: any;
}
A FetchError
is returned from a failed call to ApolloFetch
is standard Error that contains the response and a possible parse error.
The parseError
is generated when the raw response is not valid JSON (when JSON.parse()
throws) and the Afterware does not add an object to the response's parsed
property.
Errors in Middleware and Afterware are propagated without modification.
FetchError extends Error {
response: ParsedResponse;
parseError?: Error;
}