XML to JSON transform using AWS API Gateway VTL

98 Views Asked by At

I have an API Gateway that accesses an S3 bucket to get a list of the contents, the following code works and yields an XML output

    // Create API Gateway
    const api = new RestApi(this, 'S3ListApi', {
      restApiName: 'S3 Bucket Listing Service',
      description: 'Service to list S3 bucket contents.',
    });

    const listContents = api.root.addResource('list-contents');
    listContents.addCorsPreflight({
      allowOrigins: ['*'],
      allowMethods: ['GET'],
      allowHeaders: ['*'],
    });

    listContents.addMethod('GET', new AwsIntegration({
        service: 's3',
        integrationHttpMethod: 'GET',
        subdomain: bucket.bucketName, // Ensure this only has the bucket name and not the full URL or ARN
        action: 'ListBucket',
        options: {
            credentialsRole: apiGatewayRole,
            integrationResponses: [{
                statusCode: '200',
                responseTemplates: {
                    'application/xml': `$input.body`
                },
                responseParameters: {
                    'method.response.header.Content-Type': "'application/xml'"
                }
            }],
        },
    }), {
        apiKeyRequired: false,
        methodResponses: [{
            statusCode: '200',
            responseParameters: {
                'method.response.header.Content-Type': true
            },
            responseModels: {
                'application/xml': new Model(this, 'XMLResponseModel', {
                    restApi: api,
                    schema: {
                        type: JsonSchemaType.STRING // You can specify a more detailed XML schema if needed
                    },
                    contentType: 'application/xml'
                })
            }
        }],
        requestParameters: {
            'method.request.querystring.prefix': true,
        }
    });

which returns an XML structure like

<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  ...
  <Contents>
    <Key>...</Key>
    ...
  </Contents>
  ...
</ListBucketResult>

But when I try to transform it to JSON using the following code, I don't get any results:

    listContents.addMethod('GET', new AwsIntegration({
        service: 's3',
        integrationHttpMethod: 'GET',
        subdomain: bucket.bucketName, // Ensure this only has the bucket name and not the full URL or ARN
        action: 'ListBucket',
        options: {
            credentialsRole: apiGatewayRole,
            integrationResponses: [{
                statusCode: '200',
                responseTemplates: {
                    'application/xml': `
                      #set($contents = $input.path('ListBucketResult.Contents'))
                      {
                        "items": [
                          #foreach($elem in $contents)
                          {
                            "key": "$elem.Key"
                          }#if($foreach.hasNext),#end
                          #end
                        ]
                      }
                    `,
                },
                responseParameters: {
                    'method.response.header.Content-Type': "'application/json'"
                }
            }],
        },
    }), {
        apiKeyRequired: false,
        methodResponses: [{
            statusCode: '200',
            responseParameters: {
                'method.response.header.Content-Type': true
            },
            responseModels: {
                'application/json': new Model(this, 'ResponseModel', {
                    restApi: api,
                    schema: {
                        type: JsonSchemaType.OBJECT,
                        properties: {
                            items: {
                                type: JsonSchemaType.ARRAY,
                                items: {
                                    type: JsonSchemaType.OBJECT,
                                    properties: {
                                        key: { type: JsonSchemaType.STRING },
                                        lastModified: { type: JsonSchemaType.STRING },
                                        etag: { type: JsonSchemaType.STRING },
                                        size: { type: JsonSchemaType.NUMBER },
                                        ownerId: { type: JsonSchemaType.STRING },
                                        ownerDisplayName: { type: JsonSchemaType.STRING },
                                        storageClass: { type: JsonSchemaType.STRING }
                                    }
                                }
                            }
                        }
                    },
                    contentType: 'application/json'
                })
            }
        }],
        requestParameters: {
            'method.request.querystring.prefix': true,
        }
    });

The $inputRoot returns the XML correctly, but the transformation is failing because items is empty.

Any advice is much appreciated.

0

There are 0 best solutions below