Configure HTTP resolvers

You are currently viewing the legacy GraphQL Transformer documentation. View latest documentation

@http

The @http directive allows you to quickly configure HTTP resolvers within your AWS AppSync API.

Definition

1directive @http(
2 method: HttpMethod
3 url: String!
4 headers: [HttpHeader]
5) on FIELD_DEFINITION
6enum HttpMethod {
7 PUT
8 POST
9 GET
10 DELETE
11 PATCH
12}
13input HttpHeader {
14 key: String
15 value: String
16}

Usage

The @http directive allows you to quickly connect HTTP or HTTPS endpoint to an AppSync API by creating an AWS AppSync HTTP resolver. To connect to an endpoint, add the @http directive to a field in your schema.graphql file. The directive allows you to define URL path parameters, and specify a query string and/or specify a request body. For example, given the definition of a post type,

1type Post {
2 id: ID!
3 title: String
4 description: String
5 views: Int
6}
7
8type Query {
9 listPosts: Post @http(url: "https://www.example.com/posts")
10}

Amplify generates the definition below that sends a request to the url when the listPosts query is used.

1type Query {
2 listPosts: Post
3}

Request Headers

The @http directive generates resolvers that can handle xml and json responses. If an HTTP method is not defined, GET is used by default. You can specify a list of static headers to be passed with the HTTP requests to your backend in your directive definition.

1type Query {
2 listPosts: Post
3 @http(
4 url: "https://www.example.com/posts"
5 headers: [{ key: "X-Header", value: "X-Header-Value" }]
6 )
7}

Path Parameters

You can create dynamic paths by specifying parameters in the directive URL by using the special :<parameter> notation. Your set of parameters can then be specified in the params input object of the query. Note that path parameters are not added to the request body or query string. You can define multiple parameters.

Given the definition

1type Query {
2 getPost: Post @http(url: "https://www.example.com/posts/:id")
3}

Amplify generates

1type Query {
2 getPost(params: QueryGetPostParamsInput!): Post
3}
4
5input QueryGetPostParamsInput {
6 id: String!
7}

You can fetch a specific post by enclosing the id in the params input object.

1query post {
2 getPost(params: { id: "POST_ID" }) {
3 id
4 title
5 }
6}

which will send

1GET /posts/POST_ID
2Host: www.example.com

Query String

You can send a query string with your request by specifying variables for your query. The query string is supported with all request methods.

Given the definition

1type Query {
2 listPosts(sort: String!, from: String!, limit: Int!): Post
3 @http(url: "https://www.example.com/posts")
4}

Amplify generates

1type Query {
2 listPosts(query: QueryListPostsQueryInput!): Post
3}
4
5input QueryListPostsQueryInput {
6 sort: String!
7 from: String!
8 limit: Int!
9}

You can query for posts using the query input object

1query posts {
2 listPosts(query: { sort: "DESC", from: "last-week", limit: 5 }) {
3 id
4 title
5 description
6 }
7}

which sends the following request:

1GET /posts?sort=DESC&from=last-week&limit=5
2Host: www.example.com

Request Body

The @http directive also allows you to specify the body of a request, which is used for POST, PUT, and PATCH requests. To create a new post, you can define the following.

1type Mutation {
2 addPost(title: String!, description: String!, views: Int): Post
3 @http(method: POST, url: "https://www.example.com/post")
4}

Amplify generates the addPost query field with the query and body input objects since this type of request also supports a query string. The generated resolver verifies that non-null arguments (e.g.: the title and description) are passed in at least one of the input objects; if not, an error is returned.

1type Mutation {
2 addPost(query: QueryAddPostQueryInput, body: QueryAddPostBodyInput): Post
3}
4
5input QueryAddPostQueryInput {
6 title: String
7 description: String
8 views: Int
9}
10
11input QueryAddPostBodyInput {
12 title: String
13 description: String
14 views: Int
15}

You can add a post by using the body input object:

1mutation add {
2 addPost(body: { title: "new post", description: "fresh content" }) {
3 id
4 }
5}

which will send

1POST /post
2Host: www.example.com
3{
4 title: "new post"
5 description: "fresh content"
6}

Specifying the environment

The @http directive allows you to use ${env} to reference the current Amplify CLI environment.

1type Query {
2 listPosts: Post @http(url: "https://www.example.com/${env}/posts")
3}

which, in the DEV environment, will send

1GET /DEV/posts
2Host: www.example.com

Specifying the region

The @http directive allows you to use ${aws_region} to reference the AWS region of your environment.

1type Query {
2 listPosts: Post @http(url: "https://www.example.com/${aws_region}/posts")
3}

which, in the us-east-1 region, will send

1GET /us-east-1/posts
2Host: www.example.com

Combining the different components

You can use a combination of parameters, query, body, headers, and environments in your @http directive definition.

Given the definition

1type Post {
2 id: ID!
3 title: String
4 description: String
5 views: Int
6 comments: [Comment]
7}
8
9type Comment {
10 id: ID!
11 content: String
12}
13
14type Mutation {
15 updatePost(
16 title: String!
17 description: String!
18 views: Int
19 withComments: Boolean
20 ): Post
21 @http(
22 method: PUT
23 url: "https://www.example.com/${env}/posts/:id"
24 headers: [{ key: "X-Header", value: "X-Header-Value" }]
25 )
26}

you can update a post with

1mutation update {
2 updatePost(
3 body: { title: "new title", description: "updated description", views: 100 }
4 params: { id: "EXISTING_ID" }
5 query: { withComments: true }
6 ) {
7 id
8 title
9 description
10 comments {
11 id
12 content
13 }
14 }
15}

which, in the DEV environment, will send

1PUT /DEV/posts/EXISTING_ID?withComments=true
2Host: www.example.com
3X-Header: X-Header-Value
4{
5 title: "new title"
6 description: "updated description"
7 views: 100
8}

Advanced cases

In some cases, you may want to send a request based on existing field data. Take a scenario where you have a post and want to fetch comments associated with the post in a single query. Let's use the previous definition of Post and Comment.

1type Post {
2 id: ID!
3 title: String
4 description: String
5 views: Int
6 comments: [Comment]
7}
8
9type Comment {
10 id: ID!
11 content: String
12}

A post can be fetched at /posts/:id and a post's comments at /posts/:id/comments. You can fetch the comments based on the post id with the following updated definition. $ctx.source is a map that contains the resolution of the parent field (Post) and gives access to id.

1type Post {
2 id: ID!
3 title: String
4 description: String
5 views: Int
6 comments: [Comment]
7 @http(url: "https://www.example.com/posts/${ctx.source.id}/comments")
8}
9
10type Comment {
11 id: ID!
12 content: String
13}
14
15type Query {
16 getPost: Post @http(url: "https://www.example.com/posts/:id")
17}

You can retrieve the comments of a specific post with the following query and selection set.

1query post {
2 getPost(params: { id: "POST_ID" }) {
3 id
4 title
5 description
6 comments {
7 id
8 content
9 }
10 }
11}

Assuming that getPost retrieves a post with the id POST_ID, the comments field is resolved by sending this request to the endpoint

1GET /posts/POST_ID/comments
2Host: www.example.com

Note that there is no check to ensure that the reference variable (here the post ID) exists. When using this technique, it is recommended to make sure the referenced field is non-null.

Generates

The @http transformer will create one HTTP datasource for each identified base URL. For example, if multiple HTTP resolvers are created that interact with the "https://www.example.com" endpoint, only a single datasource is created. Each directive generates one resolver. Depending on the definition, the appropriate body, params, and query input types are created. Note that @http transformer does not support calling other AWS services where Signature Version 4 signing process is required.