The request URL is not available as a parameter on the onError
callback.
Clients only include a single terminating link -- usually an HttpLink
or BatchHttpLink
. The only exception to this is when we use the split
function to support both a WebSocketLink
and another terminating link. All that to say your client will generally have a single HttpLink
and that link will have a single URL for making requests -- i.e. you'll typically have just the one request URL per client. Unless you're using a custom link or an otherwise atypical setup, given a particular client you should already have access to this URL outside the context of the onError
callback.
EDIT:
I would suggest a more traditional approach to load balancing rather than trying to do this client-side (for example, using an actual load balancer or implementing the functionality with nginx). This way, your client would only have one URL to use whether for the initial request or a retry and deciding which server to use for the request would be handled by the backend.
That said, you should be able to achieve what you're trying to do by utilizing context and the split
function. Something like this should work:
import { setContext } from 'apollo-link-context'
import { createHttpLink } from 'apollo-link-http'
import { split, from } from 'apollo-link'
const contextLink = setContext(() => ({
// you could return something other than the URI here, like a number
// we just need some value that's unique to each link
targetURI: getOneURIFromURIList()
}))
const optionalHttpLink1 = split(
(operation) => operation.getContext().targetURI === URI_1,
createHttpLink({ uri: URI_1 })
)
const optionalHttpLink2 = split(
(operation) => operation.getContext().targetURI === URI_2,
createHttpLink({ uri: URI_2 })
)
const optionalHttpLink3 = split(
(operation) => operation.getContext().targetURI === URI_3,
createHttpLink({ uri: URI_3 })
)
const errorLink = onError(({ operation }) => {
// call operation.getContext().targetURI to determine the URI used
})
const link = from([
contextLink,
optionalHttpLink1,
optionalHttpLink2,
optionalHttpLink3,
errorLink,
])
You'll also want to make sure you drop the customFetch option for the above to work.
Also note that split
takes a second link as an optional third parameter. So with two parameters, you specify the condition and a link to use if the condition is met. With three parameters, you specify a condition, a link to use if the condition is met and a link to use if the condition is not met. All that to say if you're only working with two URIs in the example above, you can use just one split
instead of three:
const httpLink = split(
(operation) => operation.getContext().targetURI === URI_1,
createHttpLink({ uri: URI_1 }),
createHttpLink({ uri: URI_2 })
)
If you have more than 2 URIs, you'll want one split
per URI.
uri
parameter of customFetch may be what I want. Is it the URI of the previous call togetOneURIFromURIList
when a retry happens? I haven't try it yet. – Neo Liuri
parameter of customFetch does not change, it is/graphql
as default. – Neo Li