Skip to content

Post request with form-data via Cloudfront

0

Hello. I have deployed my backend code in ec2(HTTP) and frontend code in s3 using cloudfront(HTTPS).

There is an api to upload files with multipart/form-data.

When I send a request without files or with 400 bytes of image, it works

But if the size is more than that, I get an error.

If I send the same request directly to the server ip address, it works well.

Is there something I need to change in the cloudfront setting?

Cloudfront Behavior for EC2 server Allowed HTTP methods = GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE Cache policy = CachingDisabled Origin request policy = AllViewer

This is the response

Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 13.225.114.90:443...
* Connected to dxpqbs6f37n1l.cloudfront.net (13.225.114.90) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.cloudfront.net
*  start date: Jul 30 00:00:00 2024 GMT
*  expire date: Jul  3 23:59:59 2025 GMT
*  subjectAltName: host "dxpqbs6f37n1l.cloudfront.net" matched cert's "*.cloudfront.net"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M01
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x55de95829150)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> POST /api/v1/post/create HTTP/2
> Host: dxpqbs6f37n1l.cloudfront.net
> user-agent: curl/7.81.0
> accept: */*
> authorization: Bearer eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhbmRzMDkyN0BuYXZlci5jb20iLCJpYXQiOjE3MjUwMjY4ODQsImV4cCI6MTcyNTAzMjg4NH0.f_Fh-iA3xexS2SGLv_3DrZ8wnyFR2T2BJ-34YZOLyHamL6dstleXOePk6Ua3L100
> content-length: 28357
> content-type: multipart/form-data; boundary=------------------------4ffa93fa10dffcf0
>
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* We are completely uploaded and fine
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< content-type: text/html
< content-length: 643
< date: Fri, 30 Aug 2024 14:00:29 GMT
< last-modified: Fri, 30 Aug 2024 13:46:21 GMT
< etag: "25b8059f825837a0d13ab1369937b373"
< x-amz-server-side-encryption: AES256
< accept-ranges: bytes
< server: AmazonS3
< x-cache: Error from cloudfront
< via: 1.1 3191831ae41fb8010dc82317a4824110.cloudfront.net (CloudFront)
< x-amz-cf-pop: ICN54-C1
< x-amz-cf-id: YLCD-w7i_rC54tED7V2ngL-rlT1nEYB_itec9aIEwUGJmmIpWS5rKg==
< age: 5630
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host dxpqbs6f37n1l.cloudfront.net left intact
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>CPAYUSIN</title><script defer="defer" src="/static/js/main.db445421.js"></script><link href="/static/css/main.b0626b1e.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>r

This is when I send a request without files

*   Trying 13.225.114.109:443...
* Connected to dxpqbs6f37n1l.cloudfront.net (13.225.114.109) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.cloudfront.net
*  start date: Jul 30 00:00:00 2024 GMT
*  expire date: Jul  3 23:59:59 2025 GMT
*  subjectAltName: host "dxpqbs6f37n1l.cloudfront.net" matched cert's "*.cloudfront.net"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M01
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x55d6e00f8eb0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> POST /api/v1/post/create HTTP/2
> Host: dxpqbs6f37n1l.cloudfront.net
> user-agent: curl/7.81.0
> accept: */*
> authorization: Bearer eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhbmRzMDkyN0BuYXZlci5jb20iLCJpYXQiOjE3MjUwNDE2NzUsImV4cCI6MTcyNTA0NzY3NX0.TM4YOdq4AXxpT1-KYW49EgaLLuNpQZ9duAWCeULTlRXztQoYw5DekCaxLqpDkRky
> content-length: 223
> content-type: multipart/form-data; boundary=------------------------0c6b3238b93f96b3
>
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* We are completely uploaded and fine
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< content-type: application/json
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
< x-content-type-options: nosniff
< x-xss-protection: 0
< cache-control: no-cache, no-store, max-age=0, must-revalidate
< pragma: no-cache
< expires: 0
< date: Fri, 30 Aug 2024 18:19:27 GMT
< x-cache: Miss from cloudfront
< via: 1.1 d3e79189173c2fa1e1bfddff07afdfe4.cloudfront.net (CloudFront)
< x-amz-cf-pop: ICN54-C1
< x-amz-cf-id: wVqDTMWl-qi0w0JEOUzh1_YscDxwnKJ_NRJ0j6RJfcUpm9lotIuV2w==
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host dxpqbs6f37n1l.cloudfront.net left intact

Enter image description here

Behavior tap

Enter image description here

Behavior for ec2 server api Enter image description here

asked a year ago473 views
7 Answers
1
Accepted Answer

You mentioned the allowed methods etc. for the EC2 instance origin, but the response in the curl trace is coming from S3 (server: AmazonS3). Was the request meant to go to S3, where it seems to have gone, or to the EC2 instance?

I'm guessing the cache behaviours of your CloudFront distribution should be configured to send the URI path /api/v1/post/create or perhaps /api/* to the EC2 instance origin and only other requests to the S3 origin, but the current configuration of the cache behaviours is sending the request to the S3 origin instead.

EXPERT
answered a year ago
EXPERT
reviewed a year ago
  • Those settings are correct. The smaller precedence will get evaluated first, so if the configuration is as you describe, the request should be getting sent to the EC2 origin and not the S3 where the response is clearly coming from. Could you share a screenshot of the "Behaviors" tab of your distribution in the CloudFront console, and check that the origin labelled as EC2 actually points to the custom origin that is the EC2 instance and not the S3 bucket?

  • I have 2 patterns. For ec2 api = /api/* (Precedence 0) For s3 bucket = * (Precedence 1)

    How can I make this request sent to ec2 server instead of s3 bucket?

    I updated new response without files

  • Another thing to check is that in the cache behaviour with precedence 0, did you set the "allowed HTTP methods" to include POST and not just GET and HEAD?

  • Yes. I allowed GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE.

    I attached behavior images

  • If you look at the configuration of the origin EC2-API-SERVER in the console, does it show as a "custom origin" and specify the DNS name of the EC2 instance as its origin domain?

0

response header with files Enter image description here

response header without files Enter image description here

answered a year ago
  • Okay, and when it's showing the "Error from cloudfront" X-Cache header in the response, when made with the files, is the "Body" still the 404 error about /index.html being missing? And the web server on the EC2 instance is still not logging the request being received?

  • Yes that is correct. If I send this request to the ec2 server direclty, it works well

  • It sounds like there might be something wrong with the requests. Would you be able to test the upload process with a regular Chrome browser and using the application, rather than simulating the requests? You could restore the cache behaviour configuration you had before if that's needed for the test. Open the Developer tools view in the browser, open the Network tab, and check the "preserve log" checkbox before testing to get the requests and headers logged in the Developer tools view.

  • One more thing you could try is to disable HTTP/2 and HTTP/3 in the settings of the CloudFront distribution, only allowing HTTP/1.0 and HTTP/1.1. That might affect the processing of the multipart form-data content.

  • I only allowed HTTP/1.0 and HTTP/1.1 now it works. Thank you so much

    I'm just curious why HTTP/2 affected this multipart form-data content. Is there some documents about this in aws?

0

That's all correct. Could you still check in the logs of the web server software on the EC2 instance if the requests that include the files are arriving there, despite the original curl output showing the response came from S3?

Also to be sure, I assume you didn't have a Lambda@Edge function configured for the cache behavior for the EC2 origin? A Lambda@Edge function could override the origin chosen by the cache behaviour before CloudFront sends the request to the origin.

If the requests are not arriving at the EC2 instance, could you perhaps simplify the configuration temporarily by setting the default cache behaviour to point to the EC2 instance instead of S3? That would ensure that all requests are sent to the EC2 instance, regardless of how they appear to be behaving.

EXPERT
answered a year ago
  • I checked the log but there was no log when the request contained files

    I don't have Lambda@Edge function.

    If I change the ec2 pattern to a default setting, how do I change the s3 path pattern?

  • You can select the "Default (*)" cache behaviour in the console, click Edit, change it to use the EC2 origin, allow all the request methods, including POST, and to use the DisableCaching cache policy. That would guarantee that all requests that CloudFront can handle get sent to the EC2 instance for troubleshooting purposes.

  • Yes but what about s3 bucket? should I change this as well?

  • The cache behaviours control to which origins requests received by CloudFront get sent. You don't need to modify the S3 origin's configuration; only chance the cache behaviour that currently points to S3 to point to the EC2 origin instead, just temporarily so that we can narrow down the problem. I'm sure your application overall won't work without the S3 bucket, but the curl test will be guaranteed to get sent to the EC2 instance, if CloudFront is able to handle the request at all.

0

This is the ec2 origin. Is this what you meant?

Enter image description here

answered a year ago
  • Yes, that looks correct. Based on these settings, the request shouldn't be going to S3, and yet that's where it seems to be going. Just to be sure there are no hidden characters in the URI path, could you run this in CloudShell, substituting your distribution ID for the first parameter value: aws cloudfront get-distribution-config --id AAAABBBBCCCCDD --query 'DistributionConfig.CacheBehaviors.Items[].[PathPattern,TargetOriginId,AllowedMethods.Items]'

  • Okay. This is the response [ [ "/api/*", "EC2-API-SERVER", [ "HEAD", "DELETE", "POST", "GET", "OPTIONS", "PUT", "PATCH" ] ] ]

0

Is this right?

Enter image description here

After this change, I get 404 not found error { "timestamp": "2024-08-31T04:39:46.877+09:00", "status": 404, "error": "Not Found", "path": "/index.html" }

answered a year ago
  • With this configuration in place, if you make the POST request with curl to /api/v1/post/create both with and without the file, what is returned? The /index.html file shouldn't be getting called when the /api/v1/post/create is requested.

0

it works well without files Enter image description here

It doesn't with files Enter image description here

answered a year ago
  • Could you show the "Headers" tab of the view where it's failing?

0

Headers with files Enter image description here

Headers without files Enter image description here

answered a year ago
  • I mean the response headers below, which are probably where it says "Headers (16)", right of "Body" and "Cookies"?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.