Skip to content

Commit

Permalink
feat(appsync): add Construct for AppSync HTTP DataSource (aws#8009)
Browse files Browse the repository at this point in the history
### Commit Message
feat(appsync): add Construct for AppSync HTTP DataSource

* ADD GraphQLApi.addHttpDataSource()
* ADD interface HttpDataSourceProps
* ADD class HttpDataSource

Closes aws#8007 
### End Commit Message

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
civilizeddev authored Jun 12, 2020
1 parent 9fb0d48 commit 0592b36
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
"devDependencies": {
"conventional-changelog-cli": "^2.0.34",
"fs-extra": "^9.0.1",
"graceful-fs": "^4.2.4",
"jsii-diff": "^1.6.0",
"jsii-pacmak": "^1.6.0",
"jsii-rosetta": "^1.6.0",
"lerna": "^3.22.1",
"standard-version": "^8.0.0",
"graceful-fs": "^4.2.4",
"typescript": "~3.8.3"
},
"resolutions-comment": "should be removed or reviewed when nodeunit dependency is dropped or adjusted",
Expand Down
37 changes: 36 additions & 1 deletion packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type Mutation {
saveCustomer(id: String!, customer: SaveCustomerInput!): Customer
removeCustomer(id: String!): Customer
saveCustomerWithFirstOrder(customer: SaveCustomerInput!, order: FirstOrderInput!, referral: String): Order
doPostOnAws: String!
}
```

Expand Down Expand Up @@ -157,6 +158,40 @@ export class ApiStack extends Stack {
requestMappingTemplate: MappingTemplate.dynamoDbDeleteItem('id', 'id'),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
});

const httpDS = api.addHttpDataSource('http', 'The http data source', 'https://aws.amazon.com/');

httpDS.createResolver({
typeName: 'Mutation',
fieldName: 'doPostOnAws',
requestMappingTemplate: MappingTemplate.fromString(`{
"version": "2018-05-29",
"method": "POST",
# if full path is https://api.xxxxxxxxx.com/posts then resourcePath would be /posts
"resourcePath": "/path/123",
"params":{
"body": $util.toJson($ctx.args),
"headers":{
"Content-Type": "application/json",
"Authorization": "$ctx.request.headers.Authorization"
}
}
}`),
responseMappingTemplate: MappingTemplate.fromString(`
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
$util.error($ctx.error.message, $ctx.error.type)
#end
## if the response status code is not 200, then return an error. Else return the body **
#if($ctx.result.statusCode == 200)
## If response is 200, return the body.
$ctx.result.body
#else
## If response is not 200, append the response to error block.
$utils.appendError($ctx.result.body, "$ctx.result.statusCode")
#end
`),
});
}
}
```
```
39 changes: 39 additions & 0 deletions packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,21 @@ export class GraphQLApi extends Construct {
});
}

/**
* add a new http data source to this API
* @param name The name of the data source
* @param description The description of the data source
* @param endpoint The http endpoint
*/
public addHttpDataSource(name: string, description: string, endpoint: string): HttpDataSource {
return new HttpDataSource(this, `${name}DS`, {
api: this,
description,
endpoint,
name,
});
}

/**
* add a new Lambda data source to this API
* @param name The name of the data source
Expand Down Expand Up @@ -751,6 +766,30 @@ export class DynamoDbDataSource extends BackedDataSource {
}
}

/**
* Properties for an AppSync http datasource
*/
export interface HttpDataSourceProps extends BaseDataSourceProps {
/**
* The http endpoint
*/
readonly endpoint: string;
}

/**
* An AppSync datasource backed by a http endpoint
*/
export class HttpDataSource extends BaseDataSource {
constructor(scope: Construct, id: string, props: HttpDataSourceProps) {
super(scope, id, props, {
httpConfig: {
endpoint: props.endpoint,
},
type: 'HTTP',
});
}
}

/**
* Properties for an AppSync Lambda datasource
*/
Expand Down
65 changes: 63 additions & 2 deletions packages/@aws-cdk/aws-appsync/test/integ.graphql.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"ApiId": {
"Fn::GetAtt": ["ApiF70053CD", "ApiId"]
},
"Definition": "type ServiceVersion {\n version: String!\n}\n\ntype Customer {\n id: String!\n name: String!\n}\n\ninput SaveCustomerInput {\n name: String!\n}\n\ntype Order {\n customer: String!\n order: String!\n}\n\ntype Query {\n getServiceVersion: ServiceVersion\n getCustomers: [Customer]\n getCustomer(id: String): Customer\n getCustomerOrdersEq(customer: String): Order\n getCustomerOrdersLt(customer: String): Order\n getCustomerOrdersLe(customer: String): Order\n getCustomerOrdersGt(customer: String): Order\n getCustomerOrdersGe(customer: String): Order\n getCustomerOrdersFilter(customer: String, order: String): Order\n getCustomerOrdersBetween(customer: String, order1: String, order2: String): Order\n}\n\ninput FirstOrderInput {\n product: String!\n quantity: Int!\n}\n\ntype Mutation {\n addCustomer(customer: SaveCustomerInput!): Customer\n saveCustomer(id: String!, customer: SaveCustomerInput!): Customer\n removeCustomer(id: String!): Customer\n saveCustomerWithFirstOrder(customer: SaveCustomerInput!, order: FirstOrderInput!, referral: String): Order\n}"
"Definition": "type ServiceVersion {\n version: String!\n}\n\ntype Customer {\n id: String!\n name: String!\n}\n\ninput SaveCustomerInput {\n name: String!\n}\n\ntype Order {\n customer: String!\n order: String!\n}\n\ntype Query {\n getServiceVersion: ServiceVersion\n getCustomers: [Customer]\n getCustomer(id: String): Customer\n getCustomerOrdersEq(customer: String): Order\n getCustomerOrdersLt(customer: String): Order\n getCustomerOrdersLe(customer: String): Order\n getCustomerOrdersGt(customer: String): Order\n getCustomerOrdersGe(customer: String): Order\n getCustomerOrdersFilter(customer: String, order: String): Order\n getCustomerOrdersBetween(customer: String, order1: String, order2: String): Order\n}\n\ninput FirstOrderInput {\n product: String!\n quantity: Int!\n}\n\ntype Mutation {\n addCustomer(customer: SaveCustomerInput!): Customer\n saveCustomer(id: String!, customer: SaveCustomerInput!): Customer\n removeCustomer(id: String!): Customer\n saveCustomerWithFirstOrder(customer: SaveCustomerInput!, order: FirstOrderInput!, referral: String): Order\n doPostOnAws: String!\n}\n"
}
},
"ApiNoneDSB4E6495F": {
Expand Down Expand Up @@ -585,6 +585,67 @@
"ApiSchema510EECD7"
]
},
"ApihttpDSServiceRole8B5C9457": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "appsync.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"ApihttpDS91F12990": {
"Type": "AWS::AppSync::DataSource",
"Properties": {
"ApiId": {
"Fn::GetAtt": [
"ApiF70053CD",
"ApiId"
]
},
"Name": "http",
"Type": "HTTP",
"Description": "The http data source",
"HttpConfig": {
"Endpoint": "https://aws.amazon.com/"
},
"ServiceRoleArn": {
"Fn::GetAtt": [
"ApihttpDSServiceRole8B5C9457",
"Arn"
]
}
}
},
"ApihttpDSMutationdoPostOnAwsResolverA9027953": {
"Type": "AWS::AppSync::Resolver",
"Properties": {
"ApiId": {
"Fn::GetAtt": [
"ApiF70053CD",
"ApiId"
]
},
"FieldName": "doPostOnAws",
"TypeName": "Mutation",
"DataSourceName": "http",
"Kind": "UNIT",
"RequestMappingTemplate": "{\n \"version\": \"2018-05-29\",\n \"method\": \"POST\",\n # if full path is https://api.xxxxxxxxx.com/posts then resourcePath would be /posts\n \"resourcePath\": \"/path/123\",\n \"params\":{\n \"body\": $util.toJson($ctx.args),\n \"headers\":{\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"$ctx.request.headers.Authorization\"\n }\n }\n }",
"ResponseMappingTemplate": "\n ## Raise a GraphQL field error in case of a datasource invocation error\n #if($ctx.error)\n $util.error($ctx.error.message, $ctx.error.type)\n #end\n ## if the response status code is not 200, then return an error. Else return the body **\n #if($ctx.result.statusCode == 200)\n ## If response is 200, return the body.\n $ctx.result.body\n #else\n ## If response is not 200, append the response to error block.\n $utils.appendError($ctx.result.body, \"$ctx.result.statusCode\")\n #end\n "
},
"DependsOn": [
"ApihttpDS91F12990",
"ApiSchema510EECD7"
]
},
"CustomerTable260DCC08": {
"Type": "AWS::DynamoDB::Table",
"Properties": {
Expand Down Expand Up @@ -634,4 +695,4 @@
"DeletionPolicy": "Delete"
}
}
}
}
36 changes: 35 additions & 1 deletion packages/@aws-cdk/aws-appsync/test/integ.graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,38 @@ orderDS.createResolver({
responseMappingTemplate: MappingTemplate.dynamoDbResultList(),
});

app.synth();
const httpDS = api.addHttpDataSource('http', 'The http data source', 'https://aws.amazon.com/');

httpDS.createResolver({
typeName: 'Mutation',
fieldName: 'doPostOnAws',
requestMappingTemplate: MappingTemplate.fromString(`{
"version": "2018-05-29",
"method": "POST",
# if full path is https://api.xxxxxxxxx.com/posts then resourcePath would be /posts
"resourcePath": "/path/123",
"params":{
"body": $util.toJson($ctx.args),
"headers":{
"Content-Type": "application/json",
"Authorization": "$ctx.request.headers.Authorization"
}
}
}`),
responseMappingTemplate: MappingTemplate.fromString(`
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
$util.error($ctx.error.message, $ctx.error.type)
#end
## if the response status code is not 200, then return an error. Else return the body **
#if($ctx.result.statusCode == 200)
## If response is 200, return the body.
$ctx.result.body
#else
## If response is not 200, append the response to error block.
$utils.appendError($ctx.result.body, "$ctx.result.statusCode")
#end
`),
});

app.synth();
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-appsync/test/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ type Mutation {
saveCustomer(id: String!, customer: SaveCustomerInput!): Customer
removeCustomer(id: String!): Customer
saveCustomerWithFirstOrder(customer: SaveCustomerInput!, order: FirstOrderInput!, referral: String): Order
}
doPostOnAws: String!
}

0 comments on commit 0592b36

Please sign in to comment.