From 111384028601477262f9d2f23ae6e2330d8fd65e Mon Sep 17 00:00:00 2001 From: Annangarachari R Date: Tue, 26 Aug 2025 18:18:35 +0530 Subject: [PATCH] added files --- .../Architecture.png | Bin 0 -> 30455 bytes .../CODE_OF_CONDUCT.md | 4 + .../CONTRIBUTING.md | 59 +++++++ .../README.md | 109 ++++++++++++ .../example-pattern.json | 51 ++++++ .../template.yaml | 165 ++++++++++++++++++ 6 files changed, 388 insertions(+) create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/Architecture.png create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CODE_OF_CONDUCT.md create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CONTRIBUTING.md create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/README.md create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/example-pattern.json create mode 100644 custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/template.yaml diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/Architecture.png b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/Architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..4b2b0add742b945235f6c7af69cfad8ecd12abf8 GIT binary patch literal 30455 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 XAkx%%=#_;2H>V2ERb}AMOoRUi5fMT! literal 0 HcmV?d00001 diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CODE_OF_CONDUCT.md b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..5b627cfa6 --- /dev/null +++ b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CODE_OF_CONDUCT.md @@ -0,0 +1,4 @@ +## Code of Conduct +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CONTRIBUTING.md b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CONTRIBUTING.md new file mode 100644 index 000000000..c4b6a1c50 --- /dev/null +++ b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional +documentation, we greatly value feedback and contributions from our community. + +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +information to effectively respond to your bug report or contribution. + + +## Reporting Bugs/Feature Requests + +We welcome you to use the GitHub issue tracker to report bugs or suggest features. + +When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already +reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: + +* A reproducible test case or series of steps +* The version of our code being used +* Any modifications you've made relevant to the bug +* Anything unusual about your environment or deployment + + +## Contributing via Pull Requests +Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: + +1. You are working against the latest source on the *main* branch. +2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. +3. You open an issue to discuss any significant work - we would hate for your time to be wasted. + +To send us a pull request, please: + +1. Fork the repository. +2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. +3. Ensure local tests pass. +4. Commit to your fork using clear commit messages. +5. Send us a pull request, answering any default questions in the pull request interface. +6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. + +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + + +## Finding contributions to work on +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. + + +## Code of Conduct +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. + + +## Security issue notifications +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. + + +## Licensing + +See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/README.md b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/README.md new file mode 100644 index 000000000..06493ecae --- /dev/null +++ b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/README.md @@ -0,0 +1,109 @@ +# HTTP API Gateway to SQS for passing custom http headers as message attributes. + +This pattern enables you to pass custom HTTP headers as message attributes when sending messages from HTTP API Gateway to an SQS queue. The headers can be configured either as static values or dynamically passed from the incoming request headers. In the default configuration, the message attribute name is set as 'MessageAttribute1' which maps to the header name 'header1' in the integration request mapping. You can customize these message attribute, header names and static values, according to your requirements by updating the requestParameters section in the SqsIntegration configuration within your SAM template. You can set the name for API Gateway and the SQS queue. + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the AWS Pricing page for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +Create an AWS account if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +- AWS CLI installed and configured +- Git Installed +- AWS Serverless Application Model (AWS SAM) installed +- In the default configuration, the message attribute name is set as 'MessageAttribute1' which maps to the header name 'header1' in the integration request mapping. You can customize these message attribute, header names and static values, according to your requirements by updating the requestParameters section in the SqsIntegration configuration within your SAM template. You can set the name for API Gateway and the SQS queue. + +## Deployment Instructions: + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + +``` +git clone https://github.com/aws-samples/serverless-patterns +``` +2. Change directory to the pattern directory: + +``` +cd _patterns-model custom-http-headers-to-sqs-message-attributes-using-http-api-gateway +``` +3. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: + +``` +sam deploy --guided --capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM CAPABILITY_NAMED_IAM +``` + +4. During the prompts enter the values corresponding to each field. The values in the square brackets are the default values, which can be overwritten once you enter the inputs. + + Stack Name: + AWS Region: + Parameter ApiGatewayName: + Parameter QueueName: + #Shows you resources changes to be deployed and require a 'Y' to initiate deploy + Confirm changes before deploy [Y/n]: Y + #SAM needs permission to be able to create roles to connect to the resources in your template + Allow SAM CLI IAM role creation [Y/n]: + #Preserves the state of previously provisioned resources when an operation fails + Disable rollback [y/N]: + Save arguments to configuration file [Y/n]: + SAM configuration file [samconfig.toml]: + SAM configuration environment [default]: + + +5. Allow SAM CLI to create IAM roles with the required permissions. +Once you have run sam deploy --guided mode once and saved arguments to a configuration file (samconfig.toml), you can use sam deploy in future to use these defaults. + +6. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for later review. + +## How it works: + +This pattern sets up the following resources: + +A HTTP API Gateway with SQS integration with configurations to map the http headers to message attributes for SQS. The HTTP API will have custom logging enabled and the logs will be sent to the Cloudwatch log group created by the pattern. An SQS queue will be created by the pattern and attached to the API Gateway with default parameters. + +In the output section, the SAM deployment returns ProvidedInputs, HttpApiEndpoint, HttpApiArn, HttpApiId, LogGroupArn, QueueArn, ApiUsageInformation, Required headers, Message body sample, RoleArn and QueueUrl. + +## Testing: + +Invoke the API Gateway with required headers and body and see the message being received with the headers as message attributes. + +- Example: (The following example is for the default configuration, you can modify the values based on your custom configuration) + CLI: curl --location 'https://.execute-api..amazonaws.com/sqs' \ + --header 'header1: value for header1 which will go as MessageAttribute1' \ + --header 'header2: value for header2 which will go as MessageAttribute2' \ + --header 'Content-Type: application/json' \ + --data '{ + "MessageBody": "Payload from client via HTTP API Gateway" + }' + +- Use Case requirements: + - Required Headers: + The following headers and their corresponding values are expected to passed along with the request when using this template + - header1's (key and value) is required for MessageAttribute1 + - header2's (key and value) is required for MessageAttribute2 + - 'static_header3' is the static value being configured for MessageAttribute3's header. Since is it configured this header is not mandatory when sending the request. + - Request Body Format: + { + "MessageBody": "Your message here" + } + + - Message received in SQS will have the following attributes. + Attributes (3) + Name: MessageAttribute1 | Type: String | Value: value for header1 which will go as MessageAttribute1 + Name: MessageAttribute2 | Type: String | Value: value for header2 which will go as MessageAttribute2 + Name: MessageAttribute3 | Type: String | Value: static_header3 + +## Cleanup +- Delete the stack: + + ``` + sam delete + ``` + +- Confirm the stack has been deleted + + ``` + aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus" + ``` + + +Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/example-pattern.json b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/example-pattern.json new file mode 100644 index 000000000..706dda10a --- /dev/null +++ b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/example-pattern.json @@ -0,0 +1,51 @@ +{ + "title": "HTTP API Gateway to SQS for passing custom http headers as message attributes.", + "description": "HTTP API Gateway to SQS for passing custom http headers as message attributes.", + "level": "300", + "framework": "SAM", + "introBox": { + "headline": "How it works", + "text": [ + "This pattern enables you to pass custom HTTP headers as message attributes when sending messages from HTTP API Gateway to an SQS queue. The headers can be configured either as static values or dynamically passed from the incoming request headers. In the default configuration, the message attribute name is set as 'MessageAttribute1' which maps to the header name 'header1' in the integration request mapping. You can customize these message attribute, header names and static values, according to your requirements by updating the requestParameters section in the SqsIntegration configuration within your SAM template. You can set the name for API Gateway and the SQS queue." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway", + "templateURL": "serverless-patterns/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway", + "projectFolder": "custom-http-headers-to-sqs-message-attributes-using-http-api-gateway", + "templateFile": "custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "HTTP API Gateway to SQS for passing custom http headers as message attributes.", + "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-aws-services.html" + } + ] + }, + "deploy": { + "text": [ + "sam deploy" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: sam delete" + ] + }, + "authors": [ + { + "name": "Annangarachari R", + "image": "https://media.licdn.com/dms/image/v2/C5603AQHDdhBrpBtWsg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1651409742725?e=1759363200&v=beta&t=7-EnqmtXjWlH2uA8oSMCwnLfFFvlWtf42-aC8NSZukw", + "bio": "Serverless Enthusiast", + "linkedin": "https://www.linkedin.com/in/annangarachari-r/", + } + ] +} diff --git a/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/template.yaml b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/template.yaml new file mode 100644 index 000000000..e142435ff --- /dev/null +++ b/custom-http-headers-to-sqs-message-attributes-using-http-api-gateway/template.yaml @@ -0,0 +1,165 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 + +Parameters: + ApiGatewayName: + Type: String + Description: Name of the API Gateway + QueueName: + Type: String + Description: Name of the SQS queue + +Resources: + # CloudWatch Log Group + ApiGatewayLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub '/aws/apigateway/${ApiGatewayName}' + RetentionInDays: 30 + + # SQS Queue + MyQueue: + Type: AWS::SQS::Queue + Properties: + QueueName: !Ref QueueName + + # API Gateway Role + ApiGatewayRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: apigateway.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: ApiGatewaySQSAndCloudWatchPolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - sqs:SendMessage + - sqs:GetQueueUrl + - sqs:SendMessageBatch + Resource: !GetAtt MyQueue.Arn + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:DescribeLogGroups + - logs:DescribeLogStreams + - logs:PutLogEvents + - logs:GetLogEvents + - logs:FilterLogEvents + Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/apigateway/${ApiGatewayName}:*' + + # HTTP API + MyHttpApi: + Type: AWS::Serverless::HttpApi + Properties: + Name: !Ref ApiGatewayName + StageName: $default + Tags: + Name: !Ref ApiGatewayName + AccessLogSettings: + DestinationArn: !GetAtt ApiGatewayLogGroup.Arn + Format: '{"account":"$context.accountId","apiId":"$context.apiId","awsEndpointRequestId":"$context.awsEndpointRequestId","domainName":"$context.domainName","domainPrefix":"$context.domainPrefix","error.message":"$context.error.message","error.responseType":"$context.error.responseType","extendedRequestId":"$context.extendedRequestId","httpMethod":"$context.httpMethod","identity.accountId":"$context.identity.accountId","identity.caller":"$context.identity.caller","identity.sourceIp":"$context.identity.sourceIp","identity.user":"$context.identity.user","identity.userAgent":"$context.identity.userAgent","identity.userArn":"$context.identity.userArn","path":"$context.path","protocol":"$context.protocol","requestId":"$context.requestId","requestTime":"$context.requestTime","requestTimeEpoch":"$context.requestTimeEpoch","resourcePath":"$context.resourcePath","stage":"$context.stage","integrationLatency":"$context.integrationLatency","integrationStatus":"$context.integrationStatus","responseLatency":"$context.responseLatency","responseLength":"$context.responseLength","status":"$context.status","integrationErrorMessage":"$context.integrationErrorMessage", "error.responseType":"$context.error.responseType"}' + DefaultRouteSettings: + ThrottlingBurstLimit: 100 + ThrottlingRateLimit: 50 + DisableExecuteApiEndpoint: false + FailOnWarnings: false + + # API Integration + SqsIntegration: + Type: AWS::ApiGatewayV2::Integration + Properties: + ApiId: !Ref MyHttpApi + IntegrationType: AWS_PROXY + IntegrationSubtype: SQS-SendMessage + CredentialsArn: !GetAtt ApiGatewayRole.Arn + RequestParameters: + QueueUrl: !Ref MyQueue + MessageBody: $request.body.MessageBody + MessageAttributes: >- + { + "MessageAttribute1": { + "DataType": "String", + "StringValue": "${request.header.header1}" + }, + "MessageAttribute2": { + "DataType": "String", + "StringValue": "${request.header.header2}" + }, + "MessageAttribute3": { + "DataType": "String", + "StringValue": "static_header3" + } + } + PayloadFormatVersion: '1.0' + + # Route + SqsRoute: + Type: AWS::ApiGatewayV2::Route + Properties: + ApiId: !Ref MyHttpApi + RouteKey: 'ANY /sqs' + Target: !Join + - / + - - integrations + - !Ref SqsIntegration + +Outputs: + # Resource ARNs and IDs + HttpApiId: + Description: HTTP API ID + Value: !Ref MyHttpApi + + HttpApiArn: + Description: HTTP API ARN + Value: !Sub arn:aws:apigateway:${AWS::Region}::/apis/${MyHttpApi} + + QueueUrl: + Description: URL of the SQS queue + Value: !Ref MyQueue + + QueueArn: + Description: ARN of the SQS queue + Value: !GetAtt MyQueue.Arn + + LogGroupArn: + Description: ARN of the CloudWatch Log Group + Value: !GetAtt ApiGatewayLogGroup.Arn + + RoleArn: + Description: ARN of the IAM Role + Value: !GetAtt ApiGatewayRole.Arn + + # API Endpoint and Usage Information + HttpApiEndpoint: + Description: API Gateway endpoint URL + Value: !Sub https://${MyHttpApi}.execute-api.${AWS::Region}.amazonaws.com + + ApiUsageInformation: + Description: API Usage Information + Value: | + Endpoint: POST https://${MyHttpApi}.execute-api.${AWS::Region}.amazonaws.com/sqs + Required Headers: + - The following headers and their corresponding values are expected to passed along with the request when using this template + - header1's (key and value) is required for MessageAttribute1 header1 + - header2's (key and value) is required for MessageAttribute2 header2 + - 'static_header3' is the static value being configured for MessageAttribute3 header. + Request Body Format: + { + "MessageBody": "Your message here" + } + + # Input Parameters Used + ProvidedInputs: + Description: Input parameters provided for this deployment + Value: !Sub | + API Gateway Name: ${ApiGatewayName} + Queue Name: ${QueueName}