I have a react app hosted in S3. It is behind a Cloudfront CDN, which is reachable via a custom domain:
console.example.com -> CDN -> S3 hosted app
I also have a serverless application acting as my backend to handle API calls from the React app. This is also behind a Cloudfront CDN, which is reachable via a custom domain:
api.example.com -> CDN -> API Gateway
The front end is correctly configured to point to api.example.com. For the API Gateway, CORS is enabled.
When I navigate to the home page and attempt to login, console.example.com/login, I get the 405 Method Not Allowed error. Login, obviously using POST
I verified that the following curl is successful, when hitting the backend via API Gateway endpoint, Cloudfront Domain and the custom domain, effectively ruling out any API Gateway issue.
curl:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"email":"name#test123.com","password":"xyz"}' \
https://api.example.com/login
In my research, I have found that S3 does not support POST. I have also found similar questions such as this and this, which were not helpful in my case unfortunately.
It is also worth noting that running my frontend and backend locally, works just fine, leaving me to think the S3 issue is my blocker here. But I'm not sure why. My POST endpoints are not trying to POST an object to the S3 bucket, they should be using the bundle.js file to hit the api endpoint.
So what am I missing? While I am not a frontend specialist, I assume others host react apps on S3 and can hit their api's just fine no?
I have intentionally not included the code as there would be a lot to digest there but am happy to include any that would be helpful, such as serverless.yml files or cloudformation templates etc. Any help would be awesome.
**** UPDATE - Added Cloudformation template for frontend Cloudfront CDN ****
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
-
# Use the Website as the origin
DomainName: !GetAtt 'Website.DomainName'
Id: !Ref Website
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
Enabled: true
HttpVersion: http2
DefaultRootObject: index.html
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
- ErrorCode: 403
ResponseCode: 200
ResponsePagePath: /index.html
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 60
ForwardedValues:
QueryString: true
Cookies:
Forward: none
# The origin id defined above
TargetOriginId: !Ref Website
ViewerProtocolPolicy: "redirect-to-https" # we want to force https
# The certificate to use when using https
Aliases:
- console.example.com
ViewerCertificate:
AcmCertificateArn: arn:aws:acm:us-east-1:11111111:certificate/11111111-fa9b-4705-b9d2-11111111
MinimumProtocolVersion: TLSv1
SslSupportMethod: sni-only
I updated CustomErrorResponses to include 405 and I no longer get "405 Method Not Allowed" error:
CustomErrorResponses:
- ErrorCode: 405
ResponseCode: 200
ResponsePagePath: /index.html
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
- ErrorCode: 403
ResponseCode: 200
ResponsePagePath: /index.html
Related
Here is sample of Ngrok file which I'm using within tunnel:
authtoken: somevalue
version: "2"
tunnels:
sometunellName
proto: http
addr: 5555
schemes:
- http
- https
host_header: rewrite
request_header:
add:
- "ngrok-skip-browser-warning:true"
log_level: debug
log_format: json
log: ngrok.log
Several common headers didn't give any new result.
The "ngrok-skip-browser-warning:true" header has to be added in the browser as the ngrok cloud side of things has to see it to skip the browser warning. With your config, you've added it in the ngrok cloud so only your app is seeing it.
~ an ngrok employee
I have set up this flow:
external world --> AWS API Gateway ---> VPC Link ---> Network Load Balancer ---> my single EC2 instance
The API Gateway is working because when I input the custom domain in my browser, it successfully visits the frontend service running on my EC2 instance.
However, for /static/js/bundle.js, I'm getting a 403 MissingAuthenticationTokenException error:
But the request to the main domain is ok:
Also, all other resources failed:
/static/js/vendors~main.chunk.js
static/js/main.chunk.js
/favicon.ico
/manifest.json
My frontend is written in React JS.
Note that it says: x-amzn-errortype: MissingAuthenticationTokenException.
But I have set the Authorization to be None:
What is going on?
I have a the following setup:
1. Application (Java microservice) deployed on app engine.
2. Custom domain mapped to hit this service:.
myfavmicroservice.project-amazing.dev.corporation.com
3. This endpoint is secured to require authentication by enabling IAP.
4. Configured ESP to intercept, authenticate and fulfill request to all
backend microservices (like above) with a common gateway endpoint.
5. Microservice is deployed using app.yaml.
6. ESP endpoint is configured using api.yaml (OpenAPI API Surface document)
This is the tutorial I am following:
https://cloud.google.com/endpoints/docs/openapi/get-started-app-engine-standard
app.yaml to deploy the microservice:
runtime: java11
entrypoint: java -jar tar/worker.jar
instance_class: F2
service: myfavmicroservice
handlers:
- url: /.*
script: this field is required, but ignored
The ESP api.yaml for describing microservice api surface is like this
swagger: "2.0"
info:
title: "My fav micro Service"
description: "Serve my favorite microservice content"
version: "1.0.0"
# This field will be replaced by the deploy_api.sh script.
host: microservice-system-gateway-5c4s43dedq-ue.a.run.app
schemes:
- https
produces:
- application/json
paths:
/myfavmicroservice:
get:
summary: Greet the user
operationId: hello
description: "Get helloworld mainpage"
x-google-backend:
address: https://myfavmicroservice.project amazing.dev.corporation.com
jwt_audience: .....
responses:
'200':
description: "Success."
schema:
type: string
'400':
description: "The IATA code is invalid or missing."
schema:
type: string
But the problem is that whenever I make request to endpoint like this:
GET
https://microservice-system-gateway-5c4s43dedq-ue.a.run.app/myfavmicroservice
I always get gateway 500 error. Upon inspection of ESP logs I am finding primarily
1. SSL Handshake Error with Error no 40
2. upstream server temporarily disabled while SSL handshaking to upstream
3. request: "GET /metadatasvc-hello HTTP/1.1", upstream: "https://[3461:f4f0:5678:a13::63]:443/myfavmicroservice
So the ESP is intercepting my request correctly, perhaps forwarding the request in correct format as well as evidenced from #3. But I am getting SSL error.
Why am I getting this error?
Ok figured out the issue. For the benefit of stackoverflow community I am posting the solution here.
I figured that if you use custom domains that you map to app engine like this in the OpenAPI Configuration (That you deploy to ESP), SSL handshake fails:
x-google-backend:
address: https://my-microservice.my-custom-domain.company.com
However if you use the default URL that is assigned by APP Engine upon startup of the microservice like this, everything is fine:
x-google-backend:
address: https://my-microservice.appspot.com
So I am trying to figure out how to use custom domain mappings in ESP OpenAPI configuration. For now though, if I do that the SSL proxying is not working inside ESP.
I have the following architecture
BROWSER <-> Play Framework 2.2.1 + AngularJS <-(REST)-> Karaf
and it works; when I introduce
BROWSER <-> Apache Revere Proxy <->Play Framework 2.2.1 + AngularJS <-(REST)-> Karaf
it works; when I add OpenID authentication
BROWSER <-> Apache Revere Proxy + OpenId Module <->Play Framework 2.2.1 + AngularJS <-(REST)-> Karaf
I get on the browser
Failed to load resource: the server responded with a status of 413
(Request Entity Too Large)
on the play framework log
Request DefaultHttpRequest(chunked: false) GET
/service/connectc/command/prototypes/null HTTP/1.1 Host:
URLXXXXXXXXX:9090 uid: XXXXXXXX
ge_gessocompanyname: Company sm_first_name: Giacomo
Cookie:......
Response DefaultHttpResponse(chunked: false) HTTP/1.1 413 FULL head
Content-Length: 0 Connection: close Server: Jetty(7.6.8.v20121106)
XXXXXX=url and my id name
Indeed the authentication module introduce a very big header with Authentication token, SAML, Cookies etc...information
any suggestion?
UPDATE: it seems an error of Karaf
I solved the issue enabling HTTPS protocol on KARAF; indeed the HTTP header is too small to host authentication (SAML) header.
I have an endpoint api named "gameApi"
I have an api called:
#ApiMethod(name = "startNewRound", path = "evaluateRound", httpMethod = HttpMethod.POST)
I'm trying to run the following task queue:
queue.add(
ofy().getTransaction(),
TaskOptions.Builder.withUrl("/_ah/api/gameApi/v1/evaluateRound")
.param("gameId", gameId.toString())
.method(TaskOptions.Method.POST)
.countdownMillis(5000));
I'm getting a 404 in the logs:
0.1.0.2 - - [14/Nov/2014:14:58:28 -0800] "POST /_ah/api/gameApi/v1/evaluateRound HTTP/1.1" 404 234 "https://some-appspot-123.appspot.com/_ah/spi/com.appspot.some_appspot_123.spi.GameAPI.playCard" "AppEngine-Google; (+http://code.google.com/appengine)" "some-appspot-123.appspot.com" ms=8 cpu_ms=21 cpm_usd=0.000026 queue_name=default task_name=62689306220576549071 instance=00c61b117c54ec2fb802c51c19fe26523ec51854 app_engine_release=1.9.16
It looks like it's hitting the HTTP and not the HTTPS page. Is there a way I can force it to use HTTPS?
In endpoints, HTTP 404 corresponds to com.google.api.server.spi.response.NotFoundException.
Is it possible that the method has not been defined in the API class, or that it doesn't have a correct annotation?
Also, it doesn't seem like it's hitting http, the trace clearly shows https as the protocol. I think it's only possible to use http on localhost.