あぼぼーぼ・ぼーぼぼ

のんびり生きたい

http.NewRequestがerrorを返すパターン

以下のPRをマージする過程で調べる必要があったのでメモしておく。

github.com

結論http.NewRequestがerrorを返すパターンは、HTTPメソッドが不正な場合と、URLのパースに失敗した場合の2パターンある。

http.NewRequestはgodocにもあるとおりhttp.NewRequestWithContextcontext.Backgroundを指定して呼び出すラッパーになっている。

// NewRequest wraps NewRequestWithContext using context.Background.
func NewRequest(method, url string, body io.Reader) (*Request, error) {
    return NewRequestWithContext(context.Background(), method, url, body)
}

https://github.com/golang/go/blob/master/src/net/http/request.go#L835-L838

NewRequestWithContextがerrorを返すパターンは、validMethodでHTTPメソッドが不正な値だった場合と、contextがnilだった場合と、urlpkg.ParseでURLのパースに失敗した場合の3パターンある。このうち、contextがnilであるパターンはhttp.NewRequestでは起こらないので、残りの2パターンとなる。

func NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error) {
    if method == "" {
        // We document that "" means "GET" for Request.Method, and people have
        // relied on that from NewRequest, so keep that working.
        // We still enforce validMethod for non-empty methods.
        method = "GET"
    }
    if !validMethod(method) {
        return nil, fmt.Errorf("net/http: invalid method %q", method)
    }
    if ctx == nil {
        return nil, errors.New("net/http: nil Context")
    }
    u, err := urlpkg.Parse(url)
    if err != nil {
        return nil, err
    }
// 省略

https://github.com/golang/go/blob/f64f12f0b32eba7d49c259480e0fa0c79eb47600/src/net/http/request.go#L862-L878

今回google/go-githubに出したPRで追加したメソッドは、内部でhttp.NewRequestにPOSTを指定しているためHTTPメソッドが不正にはならないし、http.NewRequest以前の処理でベースとなるGitHub APIのURLと結合させる処理の中でURLパースをしているため、errorを返すケースは存在しないと思うが、テストカバレッジ上はカバーされていないためどうしようか?となった。起こり得なさそうとはいえ、プロダクションコードでブランク識別子でerrorを握りつぶすのは悩ましいし、errcheckのような静的解析ツールを使っている場合警告が出る。今回は、テストケースとしてはカバーしないことになったが、設計に改善の余地があるのだと思う。