Skip to content

SAM Local Testing of POST Function Produces 415 Error #259

@chadothompson

Description

@chadothompson
  • Framework version: 1.3.1 (Spring Boot 2.1.4.RELEASE)
  • Implementations: Spring Boot

Deploy / Run: SAM local. (Eventually to AWS Lambda / API Gateway, but would like to run / test some things locally before deploying.)

Scenario

I've created a rather simple application that performs a GET and POST operations. The eventual goal will be to store 'Domain' objects (simple POJO). I'm able to make the GET operation work, but the POST operation returns an error. Most of this is built on top of the spring boot sample.

The POST operation fails with a 415 "unsupported content type" error.

Here is a snippet of my controller:

  @RequestMapping(path = "/domain", method = RequestMethod.GET)
    public Map<String, Domain> getDomains() {
        HashMap<String, Domain> domainHashMap = new HashMap<>();
        Domain oneDomain = new Domain("one.com", "GOOD");
        domainHashMap.put(oneDomain.getDomainName(), oneDomain);
        Domain twoDomain = new Domain("two.com", "BAD");
        domainHashMap.put(twoDomain.getDomainName(), twoDomain);
        return domainHashMap;
    }

    @RequestMapping(path = "/domain", method = RequestMethod.POST)
    public Domain createDomain(@RequestBody Domain domain) {
        logger.info("Domain: " + domain.getDomainName());
        return new Domain(domain.getDomainName(), domain.getReputation());
    }

My test event (An API Gateway trigger - running this using the IntelliJ AWS Toolkit, though I can reproduce the error with simple 'sam invoke' on the command line.)

{
  "body": "{\"domainName\":\"mydomain.com\"}",
  "resource": "/{proxy+}",
  "path": "/domain",
  "httpMethod": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "1234567890.execute-api.{dns_suffix}",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "apiKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "resourcePath": "/{proxy+}",
    "httpMethod": "POST",
    "apiId": "1234567890"
  }
}

Expected behavior

I would expect the post to succeed and return the new 'Domain' object, while logging a line about the Domain to output.

Actual behavior

The function returns a 415 error:

{"statusCode":415,"multiValueHeaders":{"Accept":["application/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, application/json, application/*+json, */*"],"Content-Type":["application/json;charset=UTF-8"]},"body":"{\"timestamp\":1558113529125,\"status\":415,\"error\":\"Unsupported Media Type\",\"message\":\"Content type 'application/octet-stream' not supported\",\"path\":\"/domain\"}","isBase64Encoded":false}

Steps to reproduce

Execute a POST using the sam invoke.

NOTE: I can get this to work by running a Spring Boot application locally using the spring-boot-starter-web package and specifying the Content-Type header. It works as I would expect "as a regular web application". There's likely something I'm not understanding with the content type being passed through a Lambda runtime.

Full log output

Entirety of the log output produced in the test run:


Fetching lambci/lambda:java8 Docker container image......
2019-05-17 12:18:41 Mounting /private/var/folders/tk/vr_q84m96nx2_0jmf0mtzhxh0000gp/T/lambdaBuild1815/Function as /var/task:ro,delegated inside runtime container
[main] INFO com.amazonaws.serverless.proxy.internal.LambdaContainerHandler - Starting Lambda Container Handler
[main] INFO com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext - 1 Spring WebApplicationInitializers detected on classpath
[background-preinit] INFO org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 6.0.16.Final

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.4.RELEASE)

[main] INFO com.dhi.protectedprofile.domain.DomainApplication - Starting DomainApplication on 46a18f3e56a5 with PID 1 (/var/task started by sbx_user1051 in /var/task)
[main] INFO com.dhi.protectedprofile.domain.DomainApplication - No active profile set, falling back to default profiles: default
[main] INFO com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext - Initializing Spring embedded WebApplicationContext
[main] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 1763 ms
[main] INFO com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext - Initializing Spring DispatcherServlet 'dispatcherServlet'
[main] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
[main] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 494 ms
[main] INFO com.dhi.protectedprofile.domain.DomainApplication - Started DomainApplication in 4.528 seconds (JVM running for 6.685)
START RequestId: f37e1ee1-483c-4a2e-8975-8d4a9465cc3f Version: $LATEST
[main] ERROR com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest - Called set character encoding to UTF-8 on a request without a content type. Character encoding will not be set
[main] WARN org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
[main] INFO com.amazonaws.serverless.proxy.internal.LambdaContainerHandler - 127.0.0.1 - [01/01/1970:00:00:00Z] "POST /error null" 415 156 "-" "Custom User Agent String" combined
END RequestId: f37e1ee1-483c-4a2e-8975-8d4a9465cc3f
REPORT RequestId: f37e1ee1-483c-4a2e-8975-8d4a9465cc3f	Duration: 246.41 ms	Billed Duration: 300 ms	Memory Size: 128 MB	Max Memory Used: 11 MB	

{"statusCode":415,"multiValueHeaders":{"Accept":["application/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, application/json, application/*+json, */*"],"Content-Type":["application/json;charset=UTF-8"]},"body":"{\"timestamp\":1558113529125,\"status\":415,\"error\":\"Unsupported Media Type\",\"message\":\"Content type 'application/octet-stream' not supported\",\"path\":\"/domain\"}","isBase64Encoded":false}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions