Skip to content

Commit

Permalink
reuseconn
Browse files Browse the repository at this point in the history
  • Loading branch information
atzoum committed Jan 7, 2023
1 parent f498879 commit 16455db
Show file tree
Hide file tree
Showing 26 changed files with 788 additions and 782 deletions.
Binary file added .DS_Store
Binary file not shown.
48 changes: 0 additions & 48 deletions .circleci/config.yml

This file was deleted.

72 changes: 33 additions & 39 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,37 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
maligned:
suggest-new: true
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 2
misspell:
locale: US
lll:
line-length: 140
gocritic:
enabled-tags:
- performance
- style
- experimental
disabled-checks:
- wrapperFunc

linters:
enable-all: true
disable:
- maligned
- prealloc
- gochecknoglobals

run:
timeout: 5m
go: '1.19'
skip-dirs:
- passes/bodyclose/testdata
- enterprise
- event-schema

issues:
exclude-rules:
- text: "weak cryptographic primitive"
linters:
- gosec
linters:
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- bodyclose
- decorder
- makezero
- nilnil
- nilerr
- rowserrcheck
- tenv
- wastedassign
- unparam
- misspell
- unconvert

service:
golangci-lint-version: 1.15.x # use the fixed version to not introduce new linters unexpectedly
issues:
exclude-use-default: true
exclude-case-sensitive: false
max-issues-per-linter: 50
max-same-issues: 10
new: false
63 changes: 37 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,70 @@
# bodyclose
# reuseconn

[![CircleCI](https://circleci.com/gh/timakin/bodyclose.svg?style=svg)](https://circleci.com/gh/timakin/bodyclose)

`bodyclose` is a static analysis tool which checks whether `res.Body` is correctly closed.
`reuseconn` is a static analysis tool which checks whether `res.Body` is correctly closed and read so that the underlying TCP connection can be reused.

## Install

You can get `bodyclose` by `go get` command.
You can get `reuseconn` by `go get` command.

```bash
$ go get -u github.com/timakin/bodyclose
$ go get -u github.com/atzoum/reuseconn
```

## How to use

`bodyclose` run with `go vet` as below when Go is 1.12 and higher.
`reuseconn` run with `go vet` as below.

```bash
$ go vet -vettool=$(which bodyclose) github.com/timakin/go_api/...
# github.com/timakin/go_api
$ go vet -vettool=$(which reuseconn) github.com/atzoum/go_api/...
# github.com/atzoum/go_api
internal/httpclient/httpclient.go:13:13: response body must be closed
```

When Go is lower than 1.12, just run `bodyclose` command with the package name (import path).

But it cannot accept some options such as `--tags`.

```bash
$ bodyclose github.com/timakin/go_api/...
~/go/src/github.com/timakin/api/internal/httpclient/httpclient.go:13:13: response body must be closed
$ reuseconn github.com/atzoum/go_api/...
~/go/src/github.com/atzoum/api/internal/httpclient/httpclient.go:13:13: response body must be closed
```

## Analyzer

`bodyclose` validates whether [*net/http.Response](https://golang.org/pkg/net/http/#Response) of HTTP request calls method `Body.Close()` such as below code.
`reuseconn` validates whether a [*net/http.Response](https://golang.org/pkg/net/http/#Response) of HTTP request is properly disposed after used. E.g.

```go
resp, err := http.Get("http://example.com/") // Wrong case
if err != nil {
// handle error
func main() {
resp, err := http.Get("http://example.com/") // Wrong case
if err != nil {
// handle error
}
body, err := ioutil.ReadAll(resp.Body)
}
body, err := ioutil.ReadAll(resp.Body)
```

This code is wrong. You must call resp.Body.Close when finished reading resp.Body.
The above code is wrong. You must properly dispose `resp.Body` when done. To avoid a scenario where you forget to read the body in some scenarios and the connection is not reused, `reuseconn` enforces disposal to be performed within a single function which performs both operations.

```go
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error

func disposeResponseBody(resp *http.Response) {
if resp != nil && resp.Body != nil {
// if the body is already read in some scenarios, the below operation becomes a no-op
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}
}

func main() {
resp, err := http.Get("http://example.com/")
defer closeResponseBody(resp) // OK
if err != nil {
// handle error
}
if resp2.StatusCode == http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
}
}
defer resp.Body.Close() // OK
body, err := ioutil.ReadAll(resp.Body)
```

In the [GoDoc of Client.Do](https://golang.org/pkg/net/http/#Client.Do) this rule is clearly described.
In the [GoDoc of http.Response](https://pkg.go.dev/net/http#Response) this rule is clearly described.

If you forget this sentence, a HTTP client cannot re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
> It is the caller's responsibility to close Body. The default HTTP client's Transport may not reuse HTTP/1.x "keep-alive" TCP connections if the Body is not read to completion and closed.
14 changes: 10 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
module github.com/timakin/bodyclose
module github.com/atzoum/reuseconn

go 1.12
go 1.18

require (
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89
github.com/gostaticanalysis/analysisutil v0.7.1
golang.org/x/tools v0.3.0
)

require (
github.com/gostaticanalysis/comment v1.4.2 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.2.0 // indirect
)
57 changes: 51 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,54 @@
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk=
github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc=
github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q=
github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM=
github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4 h1:d2/eIbH9XjD1fFwD5SHv8x168fjbQ9PB8hvs8DSEC08=
github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA=
github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89 h1:iWXXYN3edZ3Nd/7I6Rt1sXrWVmhF9bgVtlEJ7BbH124=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
6 changes: 2 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// +build !go1.12

package main

import (
"github.com/timakin/bodyclose/passes/bodyclose"
"github.com/atzoum/reuseconn/reuseconn"
"golang.org/x/tools/go/analysis/singlechecker"
)

func main() { singlechecker.Main(bodyclose.Analyzer) }
func main() { singlechecker.Main(reuseconn.Analyzer) }
20 changes: 0 additions & 20 deletions main_go112.go

This file was deleted.

Loading

0 comments on commit 16455db

Please sign in to comment.