0

I have an Appsync Schema which defines a User type which itself contains a List of Notes:

type User {
  id: ID!
  name: String!
  notes: [Note]
}

type Note {
  id: ID!
  text: String!
}

In the request mapping for the User, I am able to access the headers from the request, to access the Bearer token:

{
    "version": "2018-05-29",
    "method": "GET",
    "resourcePath": $util.toJson("/prod/user/$ctx.args.userId"),
    "params":{
        "headers":{
            "Content-Type": "application/json",
            "Authorization": "Bearer $ctx.request.headers.Authorization",
        }
    }
}

This works well and the header is passed to the data source.

The resolver for the User.notes field is a Lambda resolver which itself iteratively calls a similar API GET /prod/user/{userId}/notes/{noteId}. I am able to access the Parent resolvers response data using $ctx.source.... However, I also need to be able to pass through the Authorization header (e.g. $ctx.request.headers.Authorization).

I have tried this in the User response mapping, but it does not work:

#set($results = $ctx.result.body)
#set($headers = {
        "Authorization": "Bearer $ctx.request.headers.Authorization"
    })
#set($results.headers = $headers)
$results

My question is, how can I pass the request headers from a Parent resolver to a Child resolver? Perhaps another way to ask the question would be, given I have a Bearer token on the Graphql request header, how can I ensure it is always passed to any resolvers which are called?

stang
  • 311
  • 3
  • 12
  • Sounds like a stupid question but just to rule out the possibility, have you tried `ctx.request.headers.Authorizationt` in your child resolver? Because `results` field is only available to response mapping template. – Myz Dec 10 '20 at 18:06
  • I did try that, but unfortunately, the `ctx.request` is emptied before the child resolver is invoked. As a test I injected the entire `$ctx` into the lambda function so I could log it out and there is nothing in there which contains the headers. This makes me think I'd need to do something with the parent resolver to cache the headers? But I don't know if that possible – stang Dec 11 '20 at 08:19
  • 1
    I believe this can easily be solved by Pipeline resolver. – Myz Dec 11 '20 at 16:21

2 Answers2

0

As @Myz mention in their comment, the solution was to use a Pipeline Resolver.

In the end, I pushed the header into the $ctx.stash object (which is available to all functions within a Pipeline Resolver) - I did this using:

$util.qr($ctx.stash.put("bearerToken", "Bearer $ctx.request.headers.Authorization"))

I was then able to access this value in each of the Functions (i.e. the child resolvers) using: "$ctx.stash.bearerToken"

stang
  • 311
  • 3
  • 12
0

Add in Note user_id

type Note {
  id: ID!
  user_id: ID!
  text: String!
}

and resolve to notes: [Note] by $ctx.source.id In postgres this appier

{
    "version": "2018-05-29",
    "statements": [
        "select * from notes where user_id = '$ctx.source.id'"
    ]
}

where $ctx.source.id link to User -> id

Yanov
  • 655
  • 7
  • 13