Apollo-link: How to pass a variable in a query flow ( from request to response )

Created on 13 Jan 2018  ·  4Comments  ·  Source: apollographql/apollo-link

My services structure is 3 layers
browser-> server(RESTful) -> Graphql <-micro services
the RESTful server works like an API proxy with an ApolloClient

so when user post a request, it first post to the RESTful server,

I know I can add headers for each query manually,
but It's not so elegant
so any idea or solution to pass the users' headers or cookies in a middleware?

fake codes

// express middleware
app.use(async (req, res, next )=> {
   // TODO: some magic to pass req.headers
}

// httpLink middleware
const middlewareLink = new ApolloLink((operation, forward, injectedArgs)=> {
  operation.setContext( 
 // TODO: do some data process for the injectedArgs
 )
  return forward(operation)
})

I don't know, for now I haven't searched any posts or docs or apis for this situation,
so feel free to discuss
It's should be a graphql-proxy? or something?
For now, seems the context only applies for direct request from browser to graphql?

question

Most helpful comment

To answer my own question...

OK, I finally make it work ( in a very limited way )
The progress is as follow,

  1. in RESTful router: get variable -> pass in as context (e.x. userId)
  2. in Middleware: get userId -> append it into herders
  3. query------->

  4. in Afterware: ( a little bit tricky here )
    before you return response, call getContext first (same as in middleware), here you got the request context, so you can get the userId for example
    then, get headers -> save the other response headers according the userId to a memory based cache

  5. finally, you can do whatever you want now

fake codes

const middelwareLink = new ApolloLink((operation, forward)=> {
  const context = operation.getContext()
  //  TODO: extract whatever you want here
  operation.setContext({
    headers: {
      //TODO: pass the variable into headers
    }
  })
  return forward(operation)
})

const afterwareLink = new ApolloLink((operation, forward) => {
  const context = operation.getContext()
  // TODO:  here what you get is the context before the request
  return forward(operation).map(response=> {
    const { response: { headers } } = operation.getContext()
    // TODO: here you get the response context (return from graphql server)
    // TODO: do some memory cache here like redis
    return response
  })
})

module.exports = middelwareLink.concat(afterwareLink).concat(httpLink)


...


client.query({
  query: MY_QUERY,
  context: {
    variables: { hello: "hello"}  // TODO: you can pass any thing here, no restrict
  }
}).then(console.log)
.catch(console.log)

  • Only works with a memory cache, no cookie, no local-storage, no res.headers

All 4 comments

To answer my own question...

OK, I finally make it work ( in a very limited way )
The progress is as follow,

  1. in RESTful router: get variable -> pass in as context (e.x. userId)
  2. in Middleware: get userId -> append it into herders
  3. query------->

  4. in Afterware: ( a little bit tricky here )
    before you return response, call getContext first (same as in middleware), here you got the request context, so you can get the userId for example
    then, get headers -> save the other response headers according the userId to a memory based cache

  5. finally, you can do whatever you want now

fake codes

const middelwareLink = new ApolloLink((operation, forward)=> {
  const context = operation.getContext()
  //  TODO: extract whatever you want here
  operation.setContext({
    headers: {
      //TODO: pass the variable into headers
    }
  })
  return forward(operation)
})

const afterwareLink = new ApolloLink((operation, forward) => {
  const context = operation.getContext()
  // TODO:  here what you get is the context before the request
  return forward(operation).map(response=> {
    const { response: { headers } } = operation.getContext()
    // TODO: here you get the response context (return from graphql server)
    // TODO: do some memory cache here like redis
    return response
  })
})

module.exports = middelwareLink.concat(afterwareLink).concat(httpLink)


...


client.query({
  query: MY_QUERY,
  context: {
    variables: { hello: "hello"}  // TODO: you can pass any thing here, no restrict
  }
}).then(console.log)
.catch(console.log)

  • Only works with a memory cache, no cookie, no local-storage, no res.headers

How to pass a variable in a query flow (only i need request )

In my codes above, you can pass variables through request to response by .setContext .getContext

Since this issue is really outdated I am closing it but if you are still concerned about this feel free to reopen and I'll get back to you asap.

Was this page helpful?
0 / 5 - 0 ratings