Related
I am attempting to build a small web application for our internal team to use to view our CloudWatch logs. Right now I'm very early in development and simply trying to access the logs via Postman using https://logs.us-east-1.amazonaws.com as specified in the AWS API official documentation.
I have followed the steps to set up my POST request to the endpoint with the following headers:
Postman Generated Headers
Also, in following with the documentation I have provided the Action in the body of this post request:
{"Action": "DescribeLogGroups"}
Using the AWS CLI this works fine and I can see all my logs groups.
When I send this request to https://logs.us-east-1.amazonaws.com I get back:
{
"Output": {
"__type": "com.amazon.coral.service#UnknownOperationException",
"message": null
},
"Version": "1.0"
}
The status code is 200.
Things I have tried:
Removing the body of the request altogether -> results in "internal server error"
appending /describeloggroups to the URL with no body -> results in "internal server error"
I'm truly not sure what I'm doing wrong here.
Best way is to set the X-Amz-Target header to Logs_20140328.DescribeLogGroups.
Here is an example request: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogGroups.html#API_DescribeLogGroups_Example_1_Request
Below is a Postman collection you can try. Save it as a file and import into Postman with File -> Import. It also requires you to set credential and region variables in postman.
{
"info": {
"name": "CloudWatch Logs",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "DescribeLogs",
"request": {
"auth": {
"type": "awsv4",
"awsv4": [
{
"key": "sessionToken",
"value": "{{SESSION_TOKEN}}",
"type": "string"
},
{
"key": "service",
"value": "logs",
"type": "string"
},
{
"key": "region",
"value": "{{REGION}}",
"type": "string"
},
{
"key": "secretKey",
"value": "{{SECRET_ACCESS_KEY}}",
"type": "string"
},
{
"key": "accessKey",
"value": "{{ACCESS_KEY_ID}}",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"warning": "This is a duplicate header and will be overridden by the Content-Type header generated by Postman.",
"key": "Content-Type",
"type": "text",
"value": "application/json"
},
{
"key": "X-Amz-Target",
"type": "text",
"value": "Logs_20140328.DescribeLogGroups"
},
{
"warning": "This is a duplicate header and will be overridden by the host header generated by Postman.",
"key": "host",
"type": "text",
"value": "logs.{{REGION}}.amazonaws.com"
},
{
"key": "Accept",
"type": "text",
"value": "application/json"
},
{
"key": "Content-Encoding",
"type": "text",
"value": "amz-1.0"
}
],
"body": {
"mode": "raw",
"raw": "{}"
},
"url": {
"raw": "https://logs.{{REGION}}.amazonaws.com",
"protocol": "https",
"host": [
"logs",
"{{REGION}}",
"amazonaws",
"com"
]
}
},
"response": []
}
],
"protocolProfileBehavior": {}
}
Try copying this into a json file and import it in Postman and add the missing variables.
I tried to get a DescribeLogGroups in the service "logs". Look in the docs here
https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DescribeLogGroups.html#API_DescribeLogGroups_Example_1_Request
for more information about the headers and body.
PS: Session token is optional, I didn't need it in my case
Hope it works for anyone who
{
"info": {
"_postman_id": "8660f3fc-fc6b-4a71-84ba-739d8b4ea7c2",
"name": "CloudWatch Logs",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "DescribeLogs",
"request": {
"auth": {
"type": "awsv4",
"awsv4": [
{
"key": "service",
"value": "{{AWS_SERVICE_NAME}}",
"type": "string"
},
{
"key": "region",
"value": "{{AWS_REGION}}",
"type": "string"
},
{
"key": "secretKey",
"value": "{{AWS_SECRET_ACCESS_KEY}}",
"type": "string"
},
{
"key": "accessKey",
"value": "{{AWS_ACCESS_KEY_ID}}",
"type": "string"
},
{
"key": "sessionToken",
"value": "",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"key": "X-Amz-Target",
"value": "Logs_20140328.DescribeLogGroups",
"type": "text"
},
{
"key": "Content-Encoding",
"value": "amz-1.0",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://{{AWS_SERVICE_NAME}}.{{AWS_REGION}}.amazonaws.com",
"protocol": "https",
"host": [
"{{AWS_SERVICE_NAME}}",
"{{AWS_REGION}}",
"amazonaws",
"com"
]
}
},
"response": []
}
]
}
I am creating and publishing APIs using WSO2 REST APIs and not from its UI because i have hundreds of WSO2 APIs to manage. I use swagger file(in json format) to configure all the details about my API and then publish this swagger file using curl command. I want to enable CORS configuration for my WSO2 APIs.
The documentation provided for WSO2 APIs provides information only about enabling CORS config via UI. Here is the link.
I could not find any info as to how i can enable it by any means other than directly from its UI. I have tried adding the following field in the API's swagger file but this change is not reflected in the published API.
"CORSConfiguration": {
"Enabled": "true",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS",
"Access-Control-Allow-Headers": "authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction",
"Access-Control-Allow-Credentials": "false"
}
Any help to enable the CORS configuration for a particular API will be appreciated. Thanks :)
CORS information should go in the API create/update payload like this.
"corsConfiguration": {
"accessControlAllowOrigins": ["*"],
"accessControlAllowHeaders": [
"authorization",
"Access-Control-Allow-Origin",
"Content-Type",
"SOAPAction"
],
"accessControlAllowMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"PATCH",
"OPTIONS"
],
"accessControlAllowCredentials": false,
"corsConfigurationEnabled": false
}
See the sample payload in [1].
[1] https://docs.wso2.com/display/AM260/apidocs/publisher/#!/operations#APIIndividual#apisPost
#Bee, here is what i tried to do.
{
"swagger": "2.0",
"info": {
"description": "Registration Type Master",
"version": "1.0",
"title": "Test_Entity_Master_API",
"termsOfService": "urn:tos",
"contact": {"name":"RD"},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0"
}
},
"host": "http://sampleurl.com/",
"basePath": "/samplemethod",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/regtype/createregtype": {
"post": {
"summary": "Create reg type entry",
"tags": [
"Registration Type Master"
],
"deprecated": false,
"produces": [
"application/json"
],
"parameters": [
{
"name": "Body",
"in": "body",
"required": true,
"description": "",
"schema": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "string"
}
}
}
}
],
"responses": {
"200": {
"description": "",
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"error": {
"type": "boolean",
"default": false
},
"message": {
"type": "string"
},
"data": {
"type": "object"
}
}
}
},
"500": {
"description": "",
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"default": false
},
"error": {
"type": "boolean"
},
"message": {
"type": "string"
},
"data": {
"type": "object"
}
}
}
}
}
}
}
},
"tags": [
{
"name": "entity-master-controller",
"description": "Entity Master Controller"
}
],
"corsConfiguration": {
"accessControlAllowOrigins": ["https://dtdevsso.ril.com"],
"accessControlAllowHeaders":[
"authorization",
"Access-Control-Allow-Origin",
"Content-Type",
"SOAPAction"
],
"accessControlAllowMethods":[
"GET",
"PUT",
"POST",
"DELETE",
"PATCH",
"OPTIONS"
],
"accessControlAllowCredentials": "true",
"corsConfigurationEnabled": "true"
}
}
In this swagger file, inspite of adding the CORS payload, it is not reflected after publishing the API through the swagger file.
To setup CORS support you must first define an OPTIONS method in your resource that returns the required headers.
All paths in swagger need a cors option chunk. this is the chunk.
"/users":
{
"options": {
"summary": "CORS support",
"description": "Enable CORS by returning correct headers\n",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"CORS"
],
"x-amazon-apigateway-integration": {
"type": "mock",
"requestTemplates": {
"application/json": "{\n \"statusCode\" : 200\n}\n"
},
"responses": {
"default": {
"statusCode": "200",
"responseParameters": {
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'",
"method.response.header.Access-Control-Allow-Methods": "'*'",
"method.response.header.Access-Control-Allow-Origin": "'*'"
},
"responseTemplates": {
"application/json": "{}\n"
}
}
}
},
"responses": {
"200": {
"description": "Default response for CORS method",
"headers": {
"Access-Control-Allow-Headers": {
"type": "string"
},
"Access-Control-Allow-Methods": {
"type": "string"
},
"Access-Control-Allow-Origin": {
"type": "string"
}
}
}
}
}
}
For more details you can visit this link
I used the following payload for creating/updating an API in WSO2.
It is working perfectly. Sorry for the delayed update on this.
{
"name": "%apiName%",
"description": "%apiDescription%",
"context": "/%apiName%",
"version": "%apiVersion%",
"provider": "%apiProvider%",
"apiDefinition": "%swaggger_extended.json% // Input swagger file",
"wsdlUri": null,
"status": "CREATED",
"responseCaching": "Disabled",
"cacheTimeout": 300,
"destinationStatsEnabled": false,
"isDefaultVersion": false,
"type": "HTTP",
"transport": [
"http",
"https"
],
"tags": ["%apiTags%"],
"tiers": ["%apiTiersCollection%"],
"visibility": "%apiVisibility%",
"visibleRoles": [],
"endpointConfig": "%endPointConfig%",
"gatewayEnvironments": "Production and Sandbox",
"subscriptionAvailability": null,
"subscriptionAvailableTenants": [],
"businessInformation": {
"businessOwnerEmail": "%BizOwnerName#ril.com%",
"technicalOwnerEmail": "%TechOwnerName#ril.com%",
"technicalOwner": "%TechOwnerName%",
"businessOwner": "%BizOwnerName%"
},
"corsConfiguration": {
"accessControlAllowOrigins": ["originURL"],
"accessControlAllowHeaders": [
"authorization",
"Access-Control-Allow-Origin",
"Content-Type",
"SOAPAction"
],
"accessControlAllowMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"PATCH",
"OPTIONS"
],
"accessControlAllowCredentials": false,
"corsConfigurationEnabled": true
}
}
I am using AWS API Gateway to consume an image file to send to a Lambda function. The POST reaches my Lambda function just fine, with the binary data transformed into a base64 string, but when I try to decode that base64 string and save it as an image, the image cannot be decoded. In fact, the string returned after transformation is smaller than the image itself, which makes me think that something is going wrong. I have tried simply returning the string provided to the Lambda function as the response and decoding that locally, which doesn't work either.
Here is the configuration for my API Gateway method:
"/photo/{photo_id}": {
"x-amazon-apigateway-any-method": {
"consumes": [
"image/jpeg",
"image/jpg"
],
"produces": [
"application/json",
"image/jpg"
],
"parameters": [
{
"name": "Content-Type",
"in": "header",
"required": false,
"type": "string"
},
{
"name": "Accept",
"in": "header",
"required": false,
"type": "string"
},
{
"name": "photo_id",
"in": "path",
"required": true,
"type": "string"
},
{
"in": "body",
"name": "Empty",
"required": true,
"schema": {
"$ref": "#/definitions/Empty"
}
},
{
"in": "body",
"name": "Empty",
"required": true,
"schema": {
"$ref": "#/definitions/Empty"
}
}
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
},
"500": {
"description": "500 response"
}
},
"x-amazon-apigateway-integration": {
"credentials": "redacted",
"uri": "redacted",
"responses": {
"default": {
"statusCode": "200"
},
".*Error.*": {
"statusCode": "500"
}
},
"requestParameters": {
"integration.request.header.Accept": "method.request.header.Accept",
"integration.request.header.Content-Type": "method.request.header.Content-Type"
},
"requestTemplates": {
"image/jpeg": "{\"photo\": \"$input.body\", \"photo_id\": \"$input.params('photo_id')\", \"app_id\": \"$input.params('x-app-id')\", \"httpMethod\": \"$context.httpMethod\"}",
"image/jpg": "{\"photo\": \"$input.body\", \"photo_id\": \"$input.params('photo_id')\", \"app_id\": \"$input.params('x-app-id')\", \"httpMethod\": \"$context.httpMethod\"}"
},
"passthroughBehavior": "when_no_templates",
"httpMethod": "POST",
"contentHandling": "CONVERT_TO_TEXT",
"type": "aws"
}
}
}
And the simple Lambda function to return the string back:
def lambda_handler(event, context):
photo_string = event['photo']
return photo_string
The cURL command I'm using to test the implementation:
curl -X POST https://execute-api.eu-central-1.amazonaws.com/prod/photo/new -H "Content-Type: image/jpg" -H "x-app-id:test" -d #IMG_1642.jpg
Any idea why the base64 that is returned would be different?
I figured it out, I needed to be using --data-binary in my cURL invocation instead of just -d which is an alias for --data-ascii. It works fine now.
I'm trying out the HTTP passthrough functionality in API gateway, passing through a resource method to another API. I want to pass through the path parameters from the API gateway URL to the backend API that also needs those path parameters.
I have the following simple Swagger document trying to test this out:
{
"swagger": "2.0",
"info": {
"version": "2017-09-15T03:33:48Z",
"title": "api-gateway-http-test"
},
"schemes": [
"https"
],
"paths": {
"/subresource/{name}": {
"get": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"uri": "http://my.web.service.url/subresource/{name}",
"passthroughBehavior": "when_no_match",
"httpMethod": "GET",
"type": "http_proxy",
"requestParameters": {
"integration.request.path.name": "method.request.path.name"
}
}
}
}
},
"definitions": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
}
}
When I try deploying this to API Gateway via CloudFormation, API Gateway gives me this error:
Unable to put integration on 'GET' for resource at path '/subresource/{name}':
Invalid mapping expression specified:
Validation Result:
warnings : [], errors : [Invalid mapping expression parameter specified: method.request.path.name]
I've looked at various sources online, and this way of configuring the "requestParameters" section seems to be the recommended way to pass through path parameters to the backend API.
What am I missing here that would cause this to not work?
It is missing parameter definitions.
Check it out with the below,
{
"swagger": "2.0",
"info": {
"version": "2017-09-15T03:33:48Z",
"title": "api-gateway-http-test"
},
"schemes": [
"https"
],
"paths": {
"/subresource/{name}": {
"get": {
"produces": [
"application/json"
],
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"uri": "http://google.com/subresource/{name}",
"passthroughBehavior": "when_no_match",
"httpMethod": "GET",
"type": "http_proxy",
"requestParameters": {
"integration.request.path.name": "method.request.path.name"
}
}
}
}
},
"definitions": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
}
}
Why currently there no way to execute AWS Lambda in asynchronous mode via Gateway API without involving intermediary Lambda just for calling invoke() method?
Even if i add integration like this:
r = client.put_integration(
restApiId=rest_api_id,
resourceId=resource_id,
httpMethod='POST',
type='AWS',
integrationHttpMethod='POST',
uri=uri,
requestParameters={
'integration.request.header.X-Amz-Invocation-Type': "'Event'",
'integration.request.header.Invocation-Type': "'Event'"
}
)
It still executed synchronously...
Are there some platform limitation or so?
I have an example Swagger document which you can switch invocation type to Lambda function. I guess you already got how to map the header to trigger the different invocation types, but I think you might forget to deploy the API.
Swagger
{
"swagger": "2.0",
"info": {
"version": "2016-02-11T22:00:31Z",
"title": "LambdaAsync"
},
"host": "<placeholder>",
"basePath": "<placeholder>",
"schemes": [
"https"
],
"paths": {
"/": {
"get": {
"produces": [
"application/json"
],
"parameters": [
{
"name": "X-Amz-Invocation-Type",
"in": "header",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"passthroughBehavior": "when_no_match",
"httpMethod": "POST",
"uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:<account>:function:<function_name>/invocations?Qualifier=$LATEST",
"responses": {
"default": {
"statusCode": "200"
}
},
"requestParameters": {
"integration.request.header.X-Amz-Invocation-Type": "method.request.header.X-Amz-Invocation-Type"
},
"type": "aws"
}
}
}
},
"definitions": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
}
}