import { ApolloLink , Observable , RequestHandler , fromError } from 'apollo-link' ; import { serializeFetchParameter , selectURI , parseAndCheckHttpResponse , checkFetcher , selectHttpOptionsAndBody , createSignalIfSupported , fallbackHttpConfig , Body , HttpOptions , UriFunction as _UriFunction , } from 'apollo-link-http-common' ; import { DefinitionNode } from 'graphql' ; export namespace HttpLink { export interface UriFunction extends _UriFunction { } export interface Options extends HttpOptions { /**
         * If set to true, use the HTTP GET method for query operations. Mutations
         * will still use the method specified in fetchOptions.method (which defaults
         * to POST).
         */ useGETForQueries ? : boolean ; } } export import FetchOptions = HttpLink . Options ; export import UriFunction = HttpLink . UriFunction ; export const createHttpLink = ( linkOptions = { } ) => { let { uri = '/graphql' , fetch : fetcher , includeExtensions , useGETForQueries , ... requestOptions } = linkOptions ; checkFetcher ( fetcher ) ; if ( ! fetcher ) { fetcher = fetch ; } const linkConfig = { http : { includeExtensions } , options : requestOptions . fetchOptions , credentials : requestOptions . credentials , headers : requestOptions . headers , } ; return new ApolloLink ( operation => { let chosenURI = selectURI ( operation , uri ) ; const context = operation . getContext ( ) ; const clientAwarenessHeaders = { } ; if ( context . clientAwareness ) { const { name , version } = context . clientAwareness ; if ( name ) { clientAwarenessHeaders [ 'apollographql-client-name' ] = name ; } if ( version ) { clientAwarenessHeaders [ 'apollographql-client-version' ] = version ; } } const contextHeaders = { ... clientAwarenessHeaders , ... context . headers } ; const contextConfig = { http : context . http , options : context . fetchOptions , credentials : context . credentials , headers : contextHeaders , } ; const { options , body } = selectHttpOptionsAndBody ( operation , fallbackHttpConfig , linkConfig , contextConfig ) ; let controller ; if ( ! ( options as any ) . signal ) { const { controller : _controller , signal } = createSignalIfSupported ( ) ; controller = _controller ; if ( controller ) ( options as any ) . signal = signal ; } const definitionIsMutation = ( d ) => { return d . kind === 'OperationDefinition' && d . operation === 'mutation' ; } ; if ( useGETForQueries && ! operation . query . definitions . some ( definitionIsMutation ) ) { options . method = 'GET' ; } if ( options . method === 'GET' ) { const { newURI , parseError } = rewriteURIForGET ( chosenURI , body ) ; if ( parseError ) { return fromError ( parseError ) ; } chosenURI = newURI ; } else { try { ( options as any ) . body = serializeFetchParameter ( body , 'Payload' ) ; } catch ( parseError ) { return fromError ( parseError ) ; } } return new Observable ( observer => { fetcher ( chosenURI , options ) . then ( response => { operation . setContext ( { response } ) ; return response ; } ) . then ( parseAndCheckHttpResponse ( operation ) ) . then ( result => { observer . next ( result ) ; observer . complete ( ) ; return result ; } ) . catch ( err => { if ( err . name === 'AbortError' ) return ; if ( err . result && err . result . errors && err . result . data ) { observer . next ( err . result ) ; } observer . error ( err ) ; } ) ; return ( ) => { if ( controller ) controller . abort ( ) ; } ; } ) ; } ) ; } ; function rewriteURIForGET ( chosenURI , body ) { const queryParams = [ ] ; const addQueryParam = ( key , value ) => { queryParams . push ( `${ key }=${ encodeURIComponent ( value ) }` ) ; } ; if ( 'query' in body ) { addQueryParam ( 'query' , body . query ) ; } if ( body . operationName ) { addQueryParam ( 'operationName' , body . operationName ) ; } if ( body . variables ) { let serializedVariables ; try { serializedVariables = serializeFetchParameter ( body . variables , 'Variables map' ) ; } catch ( parseError ) { return { parseError } ; } addQueryParam ( 'variables' , serializedVariables ) ; } if ( body . extensions ) { let serializedExtensions ; try { serializedExtensions = serializeFetchParameter ( body . extensions , 'Extensions map' ) ; } catch ( parseError ) { return { parseError } ; } addQueryParam ( 'extensions' , serializedExtensions ) ; } let fragment = '' , preFragment = chosenURI ; const fragmentStart = chosenURI . indexOf ( '#' ) ; if ( fragmentStart !== - 1 ) { fragment = chosenURI . substr ( fragmentStart ) ; preFragment = chosenURI . substr ( 0 , fragmentStart ) ; } const queryParamsPrefix = preFragment . indexOf ( '?' ) === - 1 ? '?' : '&' ; const newURI = preFragment + queryParamsPrefix + queryParams . join ( '&' ) + fragment ; return { newURI } ; } export class HttpLink extends ApolloLink { public requester : RequestHandler ; constructor ( opts ? ) { super ( createHttpLink ( opts ) . request ) ; } }