Gracefully handling application exceptions in a Tornado application

之前在DigitalOcean 的主機上用wordpress架了一個web site站台,只使用了 port 80, 後來在 443 port 架了 tornado, 滿神奇的,tornado 可以直接使用 letsencrypt 的憑證檔案。

後來發現 googlebot 會來parse 443 port 裡的資料。所以我希望 404 錯誤的資料就從80 port 裡重新取得一次,丟給Google.


取得 ssl 憑證

首先,是 letsencrypt 的 certbot 的官方說明:
https://certbot.eff.org/#ubuntuxenial-other

照上面教學的指令下,只用一行就可以產生憑證。知道網站的根目錄用這行(指令1號):

letsencrypt certonly --webroot -w /var/www/example -d example.com

如果你完全沒有網站,可以使用這行(指令2號):

letsencrypt certonly --standalone -d example.com -d www.example.com

指令1號,letsencrypt 會放東西在 webroot 目錄裡,然後letsencrypt用 80 port 連回我們伺服器進去測試。

指令2號,會自動產生一個 80 port 的 service,然後letsencrypt用 80 port 連回我們伺服器進去測試。

這2個指令,都會因此去使用 443 port,實際上原理不需要了解太多,certbot 寫的滿聰明的,會在畫面上有提醒。產生完,手動測一下 renew,沒問題的把把 renew 指令放進排程裡。

letsencrypt renew --dry-run --agree-tos

成功後就會在ubuntu的/etc/letsencrypt/archive/ 下面看到憑證了。

 

在 80和443 port 都已經被其他程式使用中的請況下,需要更進階的設定,參考看看這一篇:

apache AH00171: Graceful restart requested, doing restart
https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/

例如:

letsencrypt certonly --standalone -d example.com --tls-sni-01-port 445 --http-01-port 82

修改Tornado的 ssl_options

tornado改程式,須追加此兩個檔案的路徑在ssl_options下面,並注意檔案權限要能被讀。

http_server = tornado.httpserver.HTTPServer(Application(),
ssl_options={
“certfile”: “cert.pem”, #自行填好路徑
“keyfile”: “privkey.pem”, #自行填好路徑
})

完成之後,研究一下 tornado 的官方文件:
http://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.settings


要使用下面的這組設定值來完成自動轉發:

  • default_handler_class and default_handler_args: This handler will be used if no other match is found; use this to implement custom 404 pages (new in Tornado 3.2).

範例寫法:

import tornado.web


class BaseHandler(tornado.web.RequestHandler):
    """
    Base handler gonna to be used instead of RequestHandler
    """
    def write_error(self, status_code, **kwargs):
        if status_code in [403, 404, 500, 503]:
            self.write('Error %s' % status_code)
        else:
            self.write('BOOM!')


class ErrorHandler(tornado.web.ErrorHandler, BaseHandler):
    """
    Default handler gonna to be used in case of 404 error
    """
    pass


class MainHandler(BaseHandler):
    """
    Main handler
    """
    def get(self):
        self.write('Hello world!')
  1. Settings. We need to define default_handler_class and default_handler_args as well
settings = {
    'default_handler_class': ErrorHandler,
    'default_handler_args': dict(status_code=404)
}
  1. Application.
application = tornado.web.Application([
    (r"/", MainHandler)
], **settings)

as result. all errors except 404 gonna be handled by BaseHandler. 404 – ErrorHandler. that’s it 🙂


我的轉發的 code:

def write_error(self, status_code, **kwargs):
    if status_code == 404:
        from lib import libHttp
        http_obj = libHttp.Http()
        http_url = "http://%s%s" % (self.request.host,self.request.uri)
        (new_html_string, http_code) = http_obj.get_http_response(http_url)
        self.set_status(http_code)
        if not new_html_string is None:
            self.write(new_html_string)
        return
    return super(BaseHandler, self).write_error(status_code, **kwargs)


我最後放棄這個作法,改安裝 Nginx(發音同engine x)是一個網頁伺服器,它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的協議鏈接,以及一個負載均衡器和一個HTTP緩存。

https://www.nginx.com/resources/wiki/start/topics/tutorials/install/

範例:

nginx 基礎設定教學
http://blog.hellojcc.tw/2015/12/07/nginx-beginner-tutorial/

 


相關文章:

apache AH00171: Graceful restart requested, doing restart
https://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *