"Failed to parse Multipart request" - Spring Boot Multipart Handling Failing in AWS Lambda with 403 Error

72 Views Asked by At

I'm encountering a 403 error when attempting to upload a file using a multipart form-data request to a Spring Boot API endpoint deployed on AWS Lambda. The endpoint works as expected locally, but fails within Lambda.

Environment

  • Spring boot version: 3.1.2
  • Java Runtime: 17
  • AWS Lambda Runtime: 17

Dependecies

  • aws-serverless-java-container-springboot3: 2.0.0-M1
  • jakarta.servlet-api: 6.0.0

API Endpoint

@AccessLevelMapping(accessLevel = AccessLevel.ADMIN)
    @RequestMapping(path = {
            "/api/attachment" }, method = RequestMethod.POST, produces = "application/json", consumes = {
                    MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE })
    public String uploadAttachments(
            @RequestPart(name = "file", required = false) MultipartFile filePart,
            @RequestPart(name = "url", required = false) String url) throws Exception {
        AccountUserInfoEntity accountUserInfoEntity = accountUserRepo
                .findUserByOsyncUserId(CurrentContext.getCurrentContext().getOsyncUserId());
        System.out.println("≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤≤  ENTERED ATTACHMENT API  ≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥≥");
        System.out.println(" :::::: File Name : " + filePart.getOriginalFilename() + " ::::::: ");
        AttachmentEntity attachmentEntity = new AttachmentEntity();
        attachmentEntity.setLogTime(System.currentTimeMillis());
        attachmentEntity.setOsyncId(accountUserInfoEntity.getOsyncId());
        attachmentEntity.setAttachmentId(RequestController.getUUID());
        attachmentEntity.setShardId(accountUserInfoEntity.getShardId());
        attachmentEntity.setOsyncUserId(accountUserInfoEntity.getOsyncUserId());

        if (filePart != null) {
            attachmentEntity.setAttachmentName(filePart.getOriginalFilename());
            attachmentEntity.setAttachmentSource("file");
            attachmentEntity.setAttachmentType(filePart.getContentType());
            attachmentEntity.setAttachmentSize(filePart.getSize());
            attachmentEntity.setAttachmentUrl(S3Handler.uploadAttachmentAndGetSignedUrl(filePart,
                    attachmentEntity));
        } else if (url != null) {
            attachmentEntity.setAttachmentUrl(url);
            attachmentEntity.setAttachmentSource("url");
        }
        SMSHandler instance = CommonUtil.getInstance(CurrentContext.getCurrentOsyncId(), null, false, null);

        if (instance.checkAttachmentIsValid(attachmentEntity, url, filePart)) {
            String maskedUrl = generateEncryptedKeyAndMaskTheUrl(attachmentEntity);
            if (!maskedUrl.isEmpty()) {
                attachmentRepo.save(attachmentEntity);
                return maskedUrl;
            }
        }
        return "";
    }

When i try to hit this api using postman while running locally it is working as expected and here's my curl request for Local environment

curl --location '{{domain}}/api/attachment'\
--header 'Content-Type: multipart/form-data' \
--form 'file=@"postman-cloud:///1eeaac81-0e5c-49a0-b3fd-cbc19b15fe93"'

It is working fine.

When i try to hit the same endpoint in Lambda function it is throwing 403 error and here's the exception message Exception: org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet

and here's the complete logs from cloudwatch

org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:122)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:110) at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:86) 
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:70)  
at xyz.oapps.osync.filter.Log.doFilter(Log.java:49)  
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)  
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) 
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)  
at com.amazonaws.serverless.proxy.internal.servlet.FilterChainHolder.doFilter(FilterChainHolder.java:90)  
at com.amazonaws.serverless.proxy.internal.servlet.AwsLambdaServletContainerHandler.doFilter(AwsLambdaServletContainerHandler.java:154)  
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:174) 
at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.handleRequest(SpringBootLambdaContainerHandler.java:47)  
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:214)  
at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:257)  
at xyz.oapps.osync.StreamLambdaHandler.handleRequest(StreamLambdaHandler.java:58)  
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)  
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)  
at java.lang.reflect.Method.invoke(Unknown Source)  
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:378)
at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:905 
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:245)  
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:197)  
at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:187)  Caused by: java.lang.UnsupportedOperationException 
at com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest.getMultipartFormParametersMap(AwsHttpServletRequest.java:506)  
at com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest.getParts(AwsProxyHttpServletRequest.java:262)  
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:93)
... 22 more
  • Troubleshooting Attempts:
    • Verified Content-Type headers.
    • Configured Lambda with maximum memory and runtime settings.

I'd appreciate any insights or solutions to address this issue and enable multipart file uploads within the Lambda environment.

0

There are 0 best solutions below