Gracefully handling application exceptions in a Tornado application

Posted in :

之前在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
http://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
http://stackoverflow.max-everyday.com/2017/02/apache-graceful-restart/

發佈留言

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