LoginSignup
1
1

More than 5 years have passed since last update.

1回だけレスポンスを返すだけのHTTPサーバー(俺得)

Posted at

タイトルの通り、1回だけリクエストに対してレスポンスを返した後にそのまま終了するHTTPサーバーのスクリプトです。
他にもうちょっとスマートな実装があっても良さそうなのですが、

主な構成要素

  • http.serverモジュールによる、シンプルなサーバー実装
  • signalモジュールによる、やっつけな終了処理

http.serverを軽く取り扱う

いわゆる「ワンライナーでHTTPサーバー」がLL系のプログラミング言語には当たり前のように備わっています。

Python3ではpython -m http.serverがそれに当たりますが、これはリクエストを処理するhandler_classにSimpleHTTPRequestHandlerを用いたものです。(--cgiを引数に与えると、CGIHTTPRequestHandlerが使われます)
SimpleHTTPRequestHandlerは実行時のカレントディレクトリをルートにする静的ファイル限定のHTTPサーバーとみなしてリクエストを処理します。

閑話休題

http.serverがサーバとして動しているインスタンスはHTTPServerなのですが、serve_forever()というメソッドしかありません。1
そのため、1回だけしかリクエストを受け付けないようにするためには、どうにかリクエストの処理の時点でサーバーには死んでもらう必要があります。

で、こんなコードを書きました。

class OnceHttpServer(HTTPServer):
    def shutdown_by_signal(self, sig_num, frame):
        self.server_close()
        sys.exit(0)

    def process_request(self, request, client_address):
        super().process_request(request, client_address)
        signal.setitimer(signal.ITIMER_REAL, 0.5, 0.5)


def run(server_class=OnceHttpServer, handler_class=SimpleHTTPRequestHandler):
    server_address = ('0.0.0.0', int(os.environ.get('PORT', 8000)))
    httpd = server_class(server_address, SimpleHTTPRequestHandler)
    signal.signal(signal.SIGALRM, httpd.shutdown_by_signal)
    httpd.serve_forever(2)

OnceHttpServerHTTPServerを継承しているのですが、1個のメソッド追加と1個のメソッド拡張を持っています。

process_request()

拡張したほう。
基本的にリクエストを受け付けた時点でその処理をするメソッドなのですが、大元の処理終了後にひたすらSIGALRMを投げ続けさせる命令を追加します。
これで、最初のリクエストを処理以降、何処かのタイミングでSIGALRMに対応された処理を実行しようとプロセスが躍起になります。

shutdown_by_signal()

追加したほう。
サーバーのクリーンアップを行なったのちに、sys.exit(0)を実行してプロセスをまるっと停止させます。
このメソッドは、run()内でSIGALRMに対する処理として登録します。

こうすることで、

  1. SIGALRMにshutdown_by_signal()を登録してからサーバー待ち受け開始
  2. 最初のリクエストを処理すると当時にSIGALRMを定期的に送信(死ぬまで)
  3. シグナルを受け付けたshutdown_by_signalが自ら死を選ぶ

こんな感じの挙動すします。

誰得?

極めて俺得です。
他の人向けの使い道としては、特定のステータスコードを返すようにしてHTTPリクエストをするクラスのモックには使えるんじゃないでしょうか。

本来、自分がやりたかったことのために作ってみたコードなのですが、
それについてはまた書きます(例によってErrBot関係です)


  1. http.serverで動かした際も基本的にはKeyboardInterupt待ちです 

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1