golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.63k stars 17.61k forks source link

cmd/vet: check for http.Error followed by other statements in handler? #15205

Open dsnet opened 8 years ago

dsnet commented 8 years ago

Using go1.6

I recently saw code that did the following:

func serveHTTP(resp http.ResponseWriter, req *http.Request) {
    ...

    if err := foo(); err != nil {
        http.Error(resp, err.Error(), http.StatusInternalServerError)
    }

    if err := bar(); err != nil {
        http.Error(resp, err.Error(), http.StatusInternalServerError)
    }
}

The assumption made was that http.Error() terminates the current handler in some magical way. Instead, Error simply sets the headers and writes the body message, and it is the programmer's responsibility to return. We should document this.

bradfitz commented 8 years ago

I also wonder whether we should write a go vet check for this too. But we should only do so if this is a common problem. Is it easy for somebody to AST-grep all public Go source code and look for an http.Error with reachable statements afterwards? (/cc @sqs, @alandonovan)

We can start with documenting this first, of course.

gopherbot commented 8 years ago

CL https://golang.org/cl/21836 mentions this issue.

alandonovan commented 8 years ago

Based on a quick scan of Google's Go code base, I think such a check would find several errors, but not without false positives. Sometimes an http.Error call and its subsequent return statement are separated by logging statements or error-counter increments. We could exempt any function calls with "log" or "Error" (or within Google, "Add") in their names. The false positives are easy to work around by transposing statements.

bradfitz commented 8 years ago

Re-opening to consider vet checks.

dmitshur commented 8 years ago

Is it easy for somebody to AST-grep all public Go source code and look for an http.Error with reachable statements afterwards?

/cc @dominikh ;)

gopherbot commented 4 years ago

Change https://golang.org/cl/214859 mentions this issue: go/analysis: add analyzer for http.Error missing termination

odeke-em commented 4 years ago

Thanks for filing and following up on this bug! A couple of years back (in 2016), on a Saturday afternoon, while @bradfitz and I were hacking on Go bugs, he mentioned this bug to me and I just remembered it about 3 weeks ago and so I've mailed out CL 214859 which implements the static analysis for pretty much all the cases except the benign branches that should be pruned i.e.

func h(w http.ResponseWriter, r *http.Request) {
    if true {
       http.Error(w, msg, code)
    }
}
func h(w http.ResponseWriter, r *http.Request) {
    {
        http.Error(w, msg, code)
    }
}

For all the other cases with missing terminating statements, and heuristically known terminating statements e.g. (log.Fatal*) it'll report the missing termination statements.

I hope to get this in for Go1.15, but couldn't do it ASAP due an emergency.