5

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
user462455
  • 12,838
  • 18
  • 65
  • 96
  • Just a clarification, your 2 scripts are not actually GAE **services** (as mentioned in the post's title), they're just different **scripts** in your app's single/`default` GAE service. You'll see the difference from my answer below - the solution *is* based on GAE services. I just noticed the potential confusing inconsistency :) – Dan Cornilescu Nov 23 '16 at 16:02

1 Answers1

9

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
Community
  • 1
  • 1
Dan Cornilescu
  • 39,470
  • 12
  • 57
  • 97
  • How do I deploy with this new structure. I tried `gcloud app delpoy web.yaml rest.yaml`, but it didn't work. Both naked domain and the api.* subdomian are served by web.yaml. Now, I am trying to deploy using the following command `gcloud app deploy web.yaml rest.yaml dispatch.yaml`. And it takes long time and there is no progress after this log statement. INFO: Uploading [/server/src/dispatch.yaml] to [899bc6aeea3e3615e45e54eefe593acf2065b6b3] – user462455 Nov 26 '16 at 20:01
  • 1
    Looks like there were unnecessary spaces in my dispatch.yaml that were causing the issue of `gcloud app deploy` getting stuck while uploading dispatch.yaml. Such a weird issue ( i was able to reproduce it to make sure it was the spaces that were causing the issue). `gcloud app deploy web.yaml rest.yaml dispatch.yaml` worked!! Thanks!!! – user462455 Nov 26 '16 at 20:11
  • i'm wondering if dispatch.yaml works with appengine flex, about to find out I guess – Randy L Aug 13 '17 at 22:04
  • 1
    @the0ther yes, `dispatch.yaml` is an app-level config, shared by all app's services while the choice of the flex vs standard environment is a service-level config (an app can mix services with different languages and environments). In fact it's specified for the flex environment as well: https://cloud.google.com/appengine/docs/flexible/python/how-requests-are-routed#routing_with_a_dispatch_file – Dan Cornilescu Aug 14 '17 at 03:38
  • i think 5 minutes after i posed the question here, i searched and landed on documentation for dispatch.yaml under the flex URL. thanks just the same! – Randy L Aug 14 '17 at 18:43