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.