JavaとPythonとGoのHTTPステータスコードの実装を調査した

はじめに

エキサイト株式会社 21卒 バックエンドエンジニアの山縣です。 Spring Boot / Javaで既存システムのリビルドを進めてHTTPステータスコードの実装を調べている途中に、ふと他の言語の実装が気になり、普段趣味で使用しているPythonとGoのソースコードを見てみました。 本記事では、JavaPython、GoのHTTPステータスコードの実装について紹介します。

調査環境

今回調査した環境は以下のとおりです。

  • JavaSpring Framework 5.3.7)
    • org/springframework/http/HttpStatus.java
  • Python 3.9.7
    • http/__init__.py
  • Go 1.17
    • src/net/http/status.go

Javaステータスコード

JavaSpring Framework)のステータスコードenumを使って実装されていました。 ステータスコードごとに要素が存在し、とてもわかりやすい実装になっています。 また、HttpStatusには2xx系のステータスコードかどうかを判定するis2xxSuccessful()メソッドや、エラーかどうかの判定するisError()メソッドが実装されています。ここに挙げたメソッド以外にもHTTPステータスコードに関係する便利なメソッドがいくつか実装されているので、必要に応じて活用していきたいです。

public enum HttpStatus {
    OK(200, Series.SUCCESSFUL, "OK"),
    CREATED(201, Series.SUCCESSFUL, "Created"),
    ACCEPTED(202, Series.SUCCESSFUL, "Accepted"),

   public boolean is2xxSuccessful() {
        return (series == Series.SUCCESSFUL);
    }


    public boolean isError() {
        return (is4xxClientError() || is5xxServerError());
    }

    private final int value;
    private final Series series;
    private final String reasonPhrase;

    HttpStatus(int value, Series series, String reasonPhrase) {
        this.value = value;
        this.series = series;
        this.reasonPhrase = reasonPhrase;
    }

    public int value() {
        return this.value;
    }
}

使い方

HttpStatusはvalue()メソッドを呼び出すことでステータスコードを取得することでき、getReasonPhrase()メソッドを呼び出すことでメッセージを取得することができます。

// 引数にHttpStatus.CREATEDを渡して実行
public void check(HttpStatus status) {
    System.out.println(status.value()); 
    // → 201
    
    System.out.println(status.getReasonPhrase());
    // → Created
}

Pythonステータスコード

Pythonの標準ライブラリのステータスコードは、IntEnumを継承して実装されていました。 Javaステータスコードの実装と比較的似ていますが、こちらはステータスコードのみ実装されており、ちょっとしたことで使える便利なメソッドの実装はありませんでした。

class HTTPStatus(IntEnum):
    OK = 200, 'OK', 'Request fulfilled, document follows'
    CREATED = 201, 'Created', 'Document created, URL follows'
    ACCEPTED = (202, 'Accepted', 'Request accepted, processing continues off-line')

使い方

HTTPStatusは、valueを呼び出すことでステータスコードを取得することができ、phraseを呼び出すことでメッセージを取得することができます。 また、IntEnumを継承しているためint型と比較することができます。

# 引数にHTTPStatus.CREATEDを渡して実行
def check(status: http.HTTPStatus):
    print(status.value)
    # → 201

    print(status.phrase)
    # → Created

    print(status == http.HTTPStatus.CREATED)
    # → True

    print(status == 201)
    # → True

Goのステータスコード

Goには上記に挙げたenumのような機能はありません。 Goでは、定数とmapを組み合わせてHTTPステータスコードを実装しています。 そのため、上記2つとは異なり、HttpStatus型のようなものはないため、ステータスコードはint型として扱わなければなりません。

package http

const (
    StatusOK       = 200 // RFC 7231, 6.3.1
    StatusCreated  = 201 // RFC 7231, 6.3.2
    StatusAccepted = 202 // RFC 7231, 6.3.3
)

var statusText = map[int]string{
    StatusOK:       "OK",
    StatusCreated:  "Created",
    StatusAccepted: "Accepted",
}

func StatusText(code int) string {
    return statusText[code]
}

使い方

とてもシンプルです!

// 引数にhttp.StatusCreatedを渡して実行
func check(code int) {
    fmt.Println(code)
    //→ 201

    fmt.Println(http.StatusText(code))
    // → Created
}

おわりに

本記事ではJavaPython、GoのHTTPステータスコードの実装についてまとめました。 実際にソースコードを比較してみると、各言語の特色が出てきて面白かったです。 最後まで読んでいただき、ありがとうございました!