-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move from github.com/gofika/util/httputil
- Loading branch information
Showing
12 changed files
with
638 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
name: Dependabot auto-merge | ||
on: pull_request_target | ||
permissions: | ||
pull-requests: write | ||
contents: write | ||
jobs: | ||
dependabot: | ||
runs-on: ubuntu-latest | ||
if: ${{ github.actor == 'dependabot[bot]' }} | ||
steps: | ||
- name: Dependabot metadata | ||
id: dependabot-metadata | ||
uses: dependabot/fetch-metadata@v1.1.1 | ||
with: | ||
github-token: "${{ secrets.GITHUB_TOKEN }}" | ||
- name: Enable auto-merge for Dependabot PRs | ||
if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch' || steps.dependabot-metadata.outputs.update-type == 'version-update:semver-minor'}} | ||
run: gh pr merge --auto --merge "$PR_URL" | ||
env: | ||
PR_URL: ${{github.event.pull_request.html_url}} | ||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: build | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@master | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@master | ||
with: | ||
go-version: ">=1.20.0" | ||
|
||
- name: Build | ||
run: go build -v ./... | ||
|
||
- name: Test | ||
run: go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic | ||
|
||
- name: Upload coverage reports to Codecov | ||
uses: codecov/codecov-action@v3 | ||
env: | ||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||
|
||
- name: Refresh Go Report Card | ||
uses: creekorful/goreportcard-action@master |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,44 @@ | ||
[![codecov](https://codecov.io/gh/gofika/httputil/branch/main/graph/badge.svg)](https://codecov.io/gh/gofika/httputil) | ||
[![Build Status](https://github.com/gofika/httputil/workflows/build/badge.svg)](https://github.com/gofika/httputil) | ||
[![go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/gofika/httputil) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/gofika/httputil)](https://goreportcard.com/report/github.com/gofika/httputil) | ||
[![Licenses](https://img.shields.io/github/license/gofika/httputil)](LICENSE) | ||
|
||
# httputil | ||
|
||
golang http utils for common use | ||
|
||
|
||
## Basic Usage | ||
|
||
### Installation | ||
|
||
To get the package, execute: | ||
|
||
```bash | ||
go get github.com/gofika/httputil | ||
``` | ||
|
||
### Example | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/gofika/httputil" | ||
) | ||
|
||
func main() { | ||
resp, err := httputil.Get("https://httpbin.org/get") | ||
if err != nil { | ||
panic(err) | ||
} | ||
type GetResp struct { | ||
URL string `json:"url"` | ||
} | ||
res, err := ReadJSON[GetResp](resp) | ||
fmt.Printf("url=%s\n", res.URL) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package httputil | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"io" | ||
"mime/multipart" | ||
"net" | ||
"net/http" | ||
"net/http/cookiejar" | ||
"net/url" | ||
"time" | ||
|
||
"golang.org/x/net/publicsuffix" | ||
) | ||
|
||
type Client struct { | ||
client *http.Client | ||
ctx context.Context | ||
opts *ClientOptions | ||
} | ||
|
||
// NewClient new client | ||
func NewClient(ctx context.Context, opts ...ClientOption) *Client { | ||
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) | ||
options := &ClientOptions{ | ||
timeout: time.Minute, | ||
dialTimeout: 30 * time.Second, | ||
keepAliveTimeout: 30 * time.Second, | ||
maxIdleConns: 100, | ||
idleConnTimeout: 90 * time.Second, | ||
tlsHandshakeTimeout: 10 * time.Second, | ||
expectContinueTimeout: 1 * time.Second, | ||
} | ||
for _, opt := range opts { | ||
opt(options) | ||
} | ||
var transport http.RoundTripper | ||
if options.proxy != "" { | ||
transport = &http.Transport{ | ||
Proxy: func(_ *http.Request) (*url.URL, error) { | ||
return url.Parse(options.proxy) | ||
}, | ||
DialContext: (&net.Dialer{ | ||
Timeout: options.dialTimeout, | ||
KeepAlive: options.keepAliveTimeout, | ||
}).DialContext, | ||
MaxIdleConns: options.maxIdleConns, | ||
IdleConnTimeout: options.idleConnTimeout, | ||
TLSHandshakeTimeout: options.tlsHandshakeTimeout, | ||
ExpectContinueTimeout: options.expectContinueTimeout, | ||
} | ||
} | ||
return &Client{ | ||
client: &http.Client{ | ||
Jar: jar, | ||
Transport: transport, | ||
}, | ||
ctx: ctx, | ||
opts: options, | ||
} | ||
} | ||
|
||
// Close close | ||
func (c *Client) Close() { | ||
c.client.CloseIdleConnections() | ||
} | ||
|
||
func (c *Client) fillHeader(header http.Header, opts *RequestOptions) { | ||
if c.opts.userAgent != "" { | ||
header.Set("User-Agent", c.opts.userAgent) | ||
} | ||
if opts.referer != "" { | ||
header.Set("Referer", opts.referer) | ||
} | ||
if opts.contentType != "" { | ||
header.Set("Content-Type", opts.contentType) | ||
} | ||
for key, values := range opts.headers { | ||
for _, value := range values { | ||
if header.Get(key) != "" { | ||
continue | ||
} | ||
header.Add(key, value) | ||
} | ||
} | ||
} | ||
|
||
// Do do | ||
func (c *Client) Do(req *http.Request, opts ...RequestOption) (resp *http.Response, err error) { | ||
options := &RequestOptions{} | ||
for _, opt := range opts { | ||
opt(options) | ||
} | ||
c.fillHeader(req.Header, options) | ||
timeout := c.opts.timeout | ||
var timeoutZero time.Duration | ||
if options.timeout != timeoutZero { | ||
timeout = options.timeout | ||
} | ||
ctx, cancel := context.WithTimeout(c.ctx, timeout) | ||
defer cancel() | ||
return c.client.Do(req.WithContext(ctx)) | ||
} | ||
|
||
// Get get | ||
func (c *Client) Get(url string, opts ...RequestOption) (resp *http.Response, err error) { | ||
req, err := http.NewRequestWithContext(c.ctx, http.MethodGet, url, nil) | ||
if err != nil { | ||
return | ||
} | ||
return c.Do(req, opts...) | ||
} | ||
|
||
// Post post | ||
func (c *Client) Post(url string, contentType string, body io.Reader, opts ...RequestOption) (resp *http.Response, err error) { | ||
req, err := http.NewRequestWithContext(c.ctx, http.MethodPost, url, body) | ||
if err != nil { | ||
return | ||
} | ||
return c.Do(req, append([]RequestOption{WithContentType(contentType)}, opts...)...) | ||
} | ||
|
||
// PostForm post form | ||
func (c *Client) PostForm(url string, data url.Values, opts ...RequestOption) (resp *http.Response, err error) { | ||
return c.Post(url, "application/x-www-form-urlencoded", bytes.NewBufferString(data.Encode()), opts...) | ||
} | ||
|
||
// PostJSON post json | ||
func (c *Client) PostJSON(url string, body any, opts ...RequestOption) (resp *http.Response, err error) { | ||
payload, err := json.Marshal(body) | ||
if err != nil { | ||
return | ||
} | ||
return c.Post(url, "application/json", bytes.NewBuffer(payload), opts...) | ||
} | ||
|
||
// PostFormFiles post form files | ||
func (c *Client) PostFormFiles(url string, data url.Values, files []*UploadFile, opts ...RequestOption) (resp *http.Response, err error) { | ||
body := new(bytes.Buffer) | ||
writer := multipart.NewWriter(body) | ||
contentType := writer.FormDataContentType() | ||
for k, i := range data { | ||
for _, j := range i { | ||
err = writer.WriteField(k, j) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
} | ||
for _, file := range files { | ||
part, err := writer.CreateFormFile(file.FieldName, file.FileName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if _, err := io.Copy(part, file.Body); err != nil { | ||
return nil, err | ||
} | ||
} | ||
if err := writer.Close(); err != nil { | ||
return nil, err | ||
} | ||
req, err := http.NewRequest(http.MethodPost, url, body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return c.Do(req, append([]RequestOption{WithContentType(contentType), WithRequestTimeout(time.Hour)}, opts...)...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package httputil | ||
|
||
const HTTPBIN_ENDPOINT = "https://httpbin.org" | ||
|
||
func endpoint(path string) string { | ||
return HTTPBIN_ENDPOINT + path | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module github.com/gofika/httputil | ||
|
||
go 1.21.6 | ||
|
||
require ( | ||
github.com/gofika/fileutil v0.0.0-20240131101026-06f7b430e64a | ||
github.com/gofika/regexputil v0.0.0-20240131104326-2f03e34692bf | ||
github.com/stretchr/testify v1.8.4 | ||
golang.org/x/net v0.20.0 | ||
golang.org/x/text v0.14.0 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/gofika/fileutil v0.0.0-20240131101026-06f7b430e64a h1:I1wpuzL0HhjVIqc0QuJsomTzzuHuDSRoNvrXDWyDS9Y= | ||
github.com/gofika/fileutil v0.0.0-20240131101026-06f7b430e64a/go.mod h1:1iv1d8ir1VA4s6JPGo2pccK0rEKOi/drjedmEjCvmLo= | ||
github.com/gofika/regexputil v0.0.0-20240131104326-2f03e34692bf h1:d4Ne7Bize9Scv0temnCXDnkVEng5Op6V09iMB42llYw= | ||
github.com/gofika/regexputil v0.0.0-20240131104326-2f03e34692bf/go.mod h1:YjO232yyw1+pMF+oSsx02NWrULX/RTdS4j/6yxb2Odo= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= | ||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= | ||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= | ||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
Oops, something went wrong.