在 GAE 中使用自定义域规范化静态站点的 URL

Canonicalize URLs for static site with custom domain in GAE

我是 运行 GAE 上的一个静态站点,使用启用了 SSL 证书的自定义域(我们称之为 example.com)。我想将 URL 规范化为 https://www.example.com/。这意味着捕获对 myproject.appspot.com、纯 HTTP、and/or 裸域的任何请求,并通过 HTTPS 重定向到 www

我知道不可能将重定向逻辑放在 app.yaml 中,但理想情况下我希望将静态文件服务逻辑保留在那里,并且只有用于重定向的应用程序代码。 (与也在应用程序代码中执行静态服务相反。)

这是我目前的情况:

文件内容 app.yaml:

runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /
  static_files: www/index.html
  upload: www/index.html

- url: /(.*)
  static_files: www/
  upload: www/(.*)

文件内容 dispatch.yaml:

dispatch:
- url: "myproject.appspot.com/*"
  module: canonicalizer

文件内容 canonicalizer.yaml:

module: canonicalizer
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: canonicalizer.app

文件内容 canonicalizer.py:

import webapp2

def get_redirect_uri(handler, *args, **kwargs):
    return 'https://www.example.com/' + kwargs.get('path')

app = webapp2.WSGIApplication([
    webapp2.Route('/<path:.*>',
    webapp2.RedirectHandler,
    defaults={'_uri': get_redirect_uri, '_code': 302}),
], debug=True)

如您所见,到目前为止我只尝试实现重定向 myproject.appspot.com。我没能让它工作; myproject.appspot.com 仍然提供内容而不是重定向到自定义域。

我看到 并将其用作上面代码的基础。我非常关注它,所以我不确定它是否过时或缺少细节。

我对webapp2不是很熟悉。也对不同框架甚至不同编程语言的解决方案持开放态度。

Mapping Custom Domains to GAE

App Engine allows applications to be served via a custom domain, such as example.com, instead of the default appspot.com address. You can create a domain mapping for your App Engine app so that it uses a custom domain.

您需要执行以下操作:

  1. 通过 Webmaster Central
  2. 验证您是域的所有者
  3. 确保您的域已经过验证。
  4. 如果需要,将您域的所有权委托给其他用户或服务帐户。
  5. 将您的域映射到您的 App Engine 应用程序。
  6. 使用列出的资源记录填写表格,包括它们的类型和规范名称(CNAME)
  7. 将此信息添加到域注册商的 DNS 配置中。

Securing Custom Domains with SSL

默认情况下,当您将自定义域映射到您的应用程序时,App Engine 会为 HTTPS 连接颁发 SSL 托管证书。 Securing your custom domains with SSL 提供了更多相关信息。


Handling URL requests that do not use HTTPS

Any URL handler can use the secure setting, including script handlers and static file handlers. If secure is set to always, requests for a URL that match this handler that do not use HTTPS are automatically redirected to the HTTPS URL with the same path. Query parameters are preserved for the redirect.

app.yaml 文件中的示例:

handlers:
- url: /youraccount/.*
  secure: always
  script: auto

结论

因此,执行这些步骤后,您应该有一个自定义域正确映射到您的 App Engine 站点,该站点使用 SSL 证书来保护自定义域。

此外,通过在您的 app.yaml 文件中添加 secure:always 处理程序,对您的 App Engine 网站发出的任何 URL 请求都将自动重定向到 HTTPS URL用同样的路径。


更新 - 使用 Google App Engine

重定向所有 URL

感谢 How to redirect all URLs with Google App Engine:

app.yaml

handlers:
- url: /.*
  script: main.py

main.py

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.redirect("https://example.com", True)

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

然后,您可以根据需要调整此代码。

正如 sllopis 在他们的回答中所说,HTTP 到 HTTPS 的重定向可以通过 secure: always 元素来实现。

我想做的其他事情需要在应用程序代码中完成。我回答中的代码是正确的,但我对服务在 GAE 中的工作方式和 dispatch.yaml 有一些困惑。这是我的最终代码:

<application root>/app.yaml

runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /
  static_files: www/index.html
  upload: www/index.html
  secure: always
  redirect_http_response_code: 301

- url: /(.*)
  static_files: www/
  upload: www/(.*)
  secure: always
  redirect_http_response_code: 301

<application root>/dispatch.yaml

dispatch:
- url: "*.appspot.com/*"
  service: canonicalizer

- url: "example.com/*"
  service: canonicalizer

<application root>/canonicalizer/app.yaml

service: canonicalizer
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: canonicalizer.app

<application root>/canonicalizer/canonicalizer.py

import webapp2

def get_redirect_uri(handler, *args, **kwargs):
    return 'https://www.justinforcentral.com/' + kwargs.get('path')

app = webapp2.WSGIApplication([
    webapp2.Route('/<path:.*>',
    webapp2.RedirectHandler,
    defaults={'_uri': get_redirect_uri, '_code': 301}),
], debug=False)

这允许完成所有重定向,同时仍然保持通过 static_files 处理程序路由静态站点的能力。

顺便说一句,我也没有意识到从应用程序根目录简单地执行 gcloud app deploy . 只会部署默认服务。要部署这整个东西,我必须 运行 gcloud app deploy . dispatch.yaml canonicalizer.