Skip to content

Instantly share code, notes, and snippets.

@revmischa
Last active January 11, 2022 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save revmischa/740bac23c85023a0b31a0f4a8206f459 to your computer and use it in GitHub Desktop.
Save revmischa/740bac23c85023a0b31a0f4a8206f459 to your computer and use it in GitHub Desktop.
AWS AppSync Call From Lambda - using the AWS NodeJS SDK v3
/*
- Enable IAM authentication
- Grant IAM permission to lambda function
*/
import { HttpRequest } from "@aws-sdk/protocol-http"
import { parseUrl } from "@aws-sdk/url-parser"
import { Response, got, RequestError } from "got"
import { GraphQLResponse } from "graphql-request/dist/types"
import { signHttpRequest } from "./signedAwsRequest"
export interface AppSyncHttpRequestArgs<T = Record<string, any>> {
query: string // graphql document
operationName: string // should match the name of the query document
variables?: T
}
export const appSyncHttpRequest = async <T>({ query, operationName, variables }: AppSyncHttpRequestArgs<T>) => {
// get appsync URL
const url = process.env.GRAPHQL_URL
// graphql query
const body = JSON.stringify({
query,
operationName,
variables,
})
// sign request
const parsedUrl = parseUrl(url)
const request = new HttpRequest({
...parsedUrl,
method: "POST",
body,
headers: {
host: parsedUrl.hostname,
"content-type": "application/json",
},
})
const signedRequest = await signHttpRequest({ service: "appsync", request })
// do AppSync HTTP request
let res: Response<string>
try {
// send graphql query to endpoint
res = await got({
method: "POST",
url,
headers: signedRequest.headers,
body: signedRequest.body,
})
} catch (ex: any) {
// HTTP error
console.error(`Failed request to ${url}`, (ex as RequestError).response?.body)
throw ex
}
// parse response
const jsonRes: GraphQLResponse<T> = JSON.parse(res.body)
if (jsonRes.errors?.length) {
// graphql error response
throw new Error(`GraphQL error response: ` + JSON.stringify(jsonRes.errors))
}
return jsonRes.data
}
import { HttpRequest } from "@aws-sdk/protocol-http"
import { SignatureV4 } from "@aws-sdk/signature-v4"
import { defaultProvider } from "@aws-sdk/credential-provider-node"
import { Sha256 } from "@aws-crypto/sha256-js"
interface SignHttpRequestArgs {
request: HttpRequest
service: string // e.g. "appsync"
region?: string
}
export const signHttpRequest = async ({ request, service, region }: SignHttpRequestArgs) => {
region = region || process.env.AWS_DEFAULT_REGION
if (!region) throw new Error("Region required")
const signer = new SignatureV4({
credentials: defaultProvider(),
region,
service,
sha256: Sha256,
})
return signer.sign(request)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment