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
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
anddefault_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!')
- Settings. We need to define
default_handler_class
anddefault_handler_args
as well
settings = {
'default_handler_class': ErrorHandler,
'default_handler_args': dict(status_code=404)
}
- 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/