Mapping a custom domain route to an application in App Engine - google-app-engine

I have a custom domain with a route that I'd like to map to my React application (create-react-app production build being served on App engine). When I map the custom domain, none of my static files are found however. I've tried updating the handlers for the app but I'm getting the same error (404 on loading css, js, manifest). My dispatch.yaml is
dispatch:
- url: "example.service.org/test"
service: my-service
Accessing example.service.org/test correctly populates the page title but none of the assets load. How do I update my handlers to serve the files correctly?

If this is working in your appspot.com domain means that your static routes works fine.
I think that the issue is caused because your service doesn't know how to address this path
/test/static
I think that are multiple solutions to this issue:
1.- Map the domain with the service without /test
dispatch:
- url: "example.service.org"
service: my-service
with this workaround if you need a test url you can add an test subdomain in order to have 2 services one in prod and another in dev/test for example
dispatch:
- url: "example.service.org"
service: my-service
- url: "test.example.service.org"
service: test-my-service
2.- define in your app.yaml this handlers
handlers:
- url: /static
static_dir: static/
- url: /test/static
static_dir: static/

Related

React app not locating .js files when deployed to custom domain with Google Cloud (GAE)

I have a React app that I am trying to get running on a custom domain app.[customDomain].com with GCP. It can't locate the static files and I'm not sure why.
The react app is deployed as a service on Google cloud (not default, is second service in project). It functions perfectly with on the Google assigned URL (https://[Service_ID]-dot-[Project_ID].ue.r.appspot.com/). When running through a custom domain, index.html loads but none of the .js files are found (so result is blank screen) and give this error:
.js files error with 404
The other service in the project (is default and a Django API) serves on the same domain perfectly well and I am aiming for the React app to serve on a app. subdomain. To achieve this I have the following dispatch.yaml
dispatch:
- url: "www.[customDomain].com/"
service: default
- url: "api.[customDomain].com/"
service: default
- url: "app.[customDomain].com/"
service: React-App
I suspect the problem is in app.yaml for the react app but I can't work out what needs changing. This is the current app.yaml
env: standard
runtime: nodejs14
service: React-App
handlers:
- url: /static
secure: always
static_dir: build/static
- url: /(.*\.(json|ico|js))$
secure: always
static_files: build/\1
upload: build/.*\.(json|ico|js)$
- url: .*
secure: always
redirect_http_response_code: 301
static_files: build/index.html
upload: build/index.html
I have tried changing "homepage" in package.json but with no success.
Aside from the dependancies, the package.json contains:
"name": "React-App",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8000",
Found the issue myself. The issue is in dispatch.yaml. The urls fields need to be [subDomain].[customDomain].com/*.
In current form it is an exact text match on URL only (with fall back to default service). This means the initial load of the page was hitting React-App service but the loading of resources was falling to the default service and so they couldn't be located. Adding * to the urls meant the resource requests were routed to the correct service.

Google App Engine routing with dispatch.yaml

I try to deploy a web app on my sandbox GCP project where there is already an app deployed. So I'm trying to play with the path to have the two web apps deployed at the same time.
My dispatch looks like this
dispatch:
- url: "*/wc/api/.*"
service: wc-api
- url: "*/wc/.*"
service: wc-front
- url: "*/.*"
service: default
When I do so, all my calls to mysandbox.appspot.com/wc/ gets redirected to my default service and I don't understand why (I can see the calls in the logs of the default service).
If this helps, here is the app.yaml of my wc-front service.
runtime: python27
api_version: 1
threadsafe: yes
service: wc-front
default_expiration: "10m"
handlers:
- url: /wc/.*
script: app.APP
login: required
secure: always
Do you see any error in this ?
(Calling directly wc-front-dot-mysandbox.appspot.com/wc/ returns the typical App Engine 404 error)
Thanks
It appears the problem was coming from the .* notation. This should only be used for the very general */.* rule.
My new - working - dispatch
dispatch:
- url: "*/wc/api/*"
service: wc-api
- url: "*/wc/*"
service: wc-front
- url: "*/.*"
service: default
Yes, indeed, you need to configure your dispatch.yaml file, for App Engine to route your application based on the URL that you set there. It seems that your service: default it's getting all URLs and redirecting them to the service set there.
Considering that, I would recommend you to take a look at the official documentation about configuring the dispatch.yaml file - you can get some better ideas on how to configure it - and this other post from the Community, where another user has a similar use case as yours, that I believe should help you.
dispatch.yaml Configuration File
How to use GAE's dispatch.yaml with multiple development environments?
Let me know if the information helped you!

AppEngine dispatch.yaml for SPA and client-side routing

I have a Go server where I have an API and a static client build folder with a SPA (Single Page Application). Since the SPA should have client-side routing, I must make sure that all paths map to the frontend. For example, http://myapp.com/djaksfjal should not show a 404 in the browser, it should always route to the routes in my SPA.
Now I also want to have a backend API, so all requests to /api should go to the Go backend.
Question: how do I set this up with AppEngine? I tried with two app.yaml files and one dispatch.yaml file but can't get it to work.
client-app.yaml
runtime: go
api_version: go1
service: default
handlers:
- url: /
static_files: build/index.html
upload: build/index.html
- url: /*
static_dir: build
server-app.yaml
runtime: go
api_version: go1
service: test-backend
handlers:
- url: /api/*
script: _go_app
dispatch.yaml
dispatch:
- url: "*/api/*"
service: test-backend
hello.go
package main
import (
"fmt"
"net/http"
"google.golang.org/appengine"
)
func main() {
http.HandleFunc("/api/hello", handle)
appengine.Main()
}
func handle(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world!")
}
Then running dev_appserver.py server-app.yaml client-app.yaml dispatch.yaml and going to localhost:8080 where the dispatch server is. However, this doesn't work. The client-side routing takes over everything, ignoring the /api/hello route.
Tested: localhost:8080/api/hello. Expecting: api route reply. Got: static client reply
If I change the client-app.yaml to not use a * then the /api/hello route works, but of course the client-side routing does not work because I need all routes to go to the client so that it can handle the routing itself (except for the /api routes).
The rules order in the dispatch.yaml file matters - the first pattern match wins. So you want the */api one first.
Also - if none of the rules pattern matches the request will be routers to the default service, no need to add a rule for that.
I also see that you mentioned an /api/hello request path - for that to work you may need to expand the */api pattern into */api/*
So I'd use this dispatch.yaml file:
dispatch:
- url: "*/api/*"
service: test-backend
You also need to expand the /api pattern in the server-app.yaml file, otherwise /api/hello will give a 404:
handlers:
- url: /api/*
script: _go_app
Side note: you shouldn't (need to) go to localhost:8080 - that'll just send you to the default service. Instead note the individual ports that the development server listens to for each module/service, displayed when the server starts.

App Engine - subdomain pointing to particular service

I have two subdomains registered in my App Engine application:
service-a.my-app.com
service-b.my-app.com
I have added all the records (CNAME, A) on the server.
I have three services in my GAE:
default
service-a
service-b
And I want each subdomain to point to the correct service. However, each time I access them, only the default service is used.
Side note: the GAE is running a flexible environment for laravel 5.4 and my dispatch.yaml (located in default service is as follows:
dispatch:
-url: "service-a.my-app.com/*"
service: service-a
-url: "service-b.my-app.com/*"
service: service-b
This worked for me. Hope this helps someone.
GAE Standard:
I have an angular project which will load for any subdomain except one subdomain "api".
The backend is written in Go and all services are under a service named "api"
STEP1: Setting local env
Angular project has the following app.yaml
runtime: python27
api_version: 1
instance_class: F1
handlers:
- url: /
static_files: default/index.html
upload: default/index.html
- url: /
static_dir: default
My service.yaml file resides in a separate directory and has the following
runtime: go
api_version: go1
instance_class: F1
service: api
handlers:
- url: /.*
script: _go_app
secure: always
My dispatch.yaml has the following
dispatch:
- url: "api.MYDOMAINNAME.com/*"
service: api
//Add more subdomain : services mapping here
I deployed all these files using gcloud app deploy command
Step 2 - Configure Custom domains in GAE.
In GAE Console, goto Project Settings > Custom Domains
Add your domain
Verify your domainusing one of the methods provided by Google.
Update CNAME, A and AAA records in your domain service provider's DNS Settings
Step 3 - Configure Sub Domain
Add a subdomain api.MYDOMAINNAME.com
Add the CNAME in your domain service provider's settings.
// add more subdomains if required
Add a Wildcard subdomain *.MYDOMAINNAME.com
Add the CNAME in your domain service provider's settings to redirect * to google.
Finally:
Wait for few minutes for the settings to be applied.
Now your application will redirect MYDOMAINNAME.com, www.MYDOMAINNAME.com , *.MYDOMAINNAME.com to the Angular code
and
api.MYDOMAINNAME.com to your api service
Please note that dispatch.yaml is an app-level configuration, not a service-level one and occasionally updating the service containing it doesn't automatically update the app-level configs.
You should use the specific deployment commands for dispatch.yaml, executed from the directory containing the file:
gcloud app deploy dispatch.yaml if you're using the Cloud SDK
appcfg.py update_dispatch . if you're still using the GAE SDK
See also dispatch.yaml not getting updated.
The same is true for other app-level .yaml config files as well, which is probably one reason for each having its own update/deploy command (and also to allow deploying them independently of any particular app service. Somehow related: Why do I need to deploy a "default" app before I can deploy multiple services in GCP?
Actually the answer was really easy: You just need to map a wildcard subdomain and GAE would the use the service corresponding to the prefix.

Mapping subdomain to a service in Google App Engine project

I have a Google App Engine project with following yaml file
handlers:
- url: /web/.*
script: web_server.app
- url: /api/.*
script: rest_server.app
How do I make sure subdomain, of a domain I own, be served by rest_server.app script.
Example: If I own example.com
I want example.com to be served by web_server.app, and api.example.com to be served by rest_server.app
Is it possible to do that using Google App Engine.
Example:
handlers:
- url: example.com/.*
script: web_server.app
- url: api.example.com/.*
script: rest_server.app
Request routing in the app.yaml can not be used to route based on the URL's domain name, see the url table row in the Handlers element doc section.
Because of that you can't really have a single module/service serving your app while simultaneously stripping the filepath portion of the URL you're currently used in your handlers' url configs for routing requests to one script or the other.
You can obtain what you desire by splitting your app into 2 separate services/modules, each handling one script. One of the modules has to be the default module, I'd make the web one the default.
A dispatch.yaml file would be used to route requests to their respective modules based on the URL hostname.
The web.yaml file would contain:
module: default
handlers:
- url: /.*
script: web_server.app
The rest.yaml file would contain:
module: rest
handlers:
- url: /.*
script: rest_server.app
In the dispatch.yaml file you only need routes for the non-default module(s), requests matching no routes are by default routed to the defaut module:
- url: "api.example.com/*"
module: rest
You can find a more complete example here: https://stackoverflow.com/a/34111170/4495081
You'd then map both your example.com naked domain and api.example.com subdomain to your app. Follow the Adding a custom domain for your application procedure, paying extra attention to the sections which are slightly different when configuring a naked domain vs a subdomain. See also https://stackoverflow.com/a/36317462/4495081
There is one problem, tho - dispatch.yaml routing based on hostnames doesn't work with the local development server, the requests destined for the rest module would actually go to the default module.
A simpler workaround would be to direct the rest module clients to the actual localhost:PORT URL where the local devserver's rest module listens (displayed in the terminal at dev server startup), instead.
This might not be possible in all cases or for all apps. For example it's an issue if the app makes cross-module requests with auto-generated URLs.
In such cases, to work around it you can temporarily insert a small path portion in the rest.yaml URL, only during testing on the local dev server the rest module (you'd need matching changes on the client side and/or the cross-module URL generation logic):
module: rest
handlers:
- url: /api/.*
script: rest_server.app
And then you can add a dispatch.yaml rule that is not host-based and would also with the local dev server. This can be left in there permanently, it doesn't hurt if/when deployed in production when the temporary rest.yaml change is reversed:
- url: "api.example.com/*"
module: rest
- url: "*/api/*"
module: rest

Resources