This commit is contained in:
parent
d7738f79e1
commit
fa74f7ad4c
72
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
72
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@ -1,5 +1,77 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v4.12.0 - 2024-04-15
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Update golang.org/x/net dep because of [GO-2024-2687](https://pkg.go.dev/vuln/GO-2024-2687) by @aldas in https://github.com/labstack/echo/pull/2625
|
||||||
|
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* binder: make binding to Map work better with string destinations by @aldas in https://github.com/labstack/echo/pull/2554
|
||||||
|
* README.md: add Encore as sponsor by @marcuskohlberg in https://github.com/labstack/echo/pull/2579
|
||||||
|
* Reorder paragraphs in README.md by @aldas in https://github.com/labstack/echo/pull/2581
|
||||||
|
* CI: upgrade actions/checkout to v4 by @aldas in https://github.com/labstack/echo/pull/2584
|
||||||
|
* Remove default charset from 'application/json' Content-Type header by @doortts in https://github.com/labstack/echo/pull/2568
|
||||||
|
* CI: Use Go 1.22 by @aldas in https://github.com/labstack/echo/pull/2588
|
||||||
|
* binder: allow binding to a nil map by @georgmu in https://github.com/labstack/echo/pull/2574
|
||||||
|
* Add Skipper Unit Test In BasicBasicAuthConfig and Add More Detail Explanation regarding BasicAuthValidator by @RyoKusnadi in https://github.com/labstack/echo/pull/2461
|
||||||
|
* fix some typos by @teslaedison in https://github.com/labstack/echo/pull/2603
|
||||||
|
* fix: some typos by @pomadev in https://github.com/labstack/echo/pull/2596
|
||||||
|
* Allow ResponseWriters to unwrap writers when flushing/hijacking by @aldas in https://github.com/labstack/echo/pull/2595
|
||||||
|
* Add SPDX licence comments to files. by @aldas in https://github.com/labstack/echo/pull/2604
|
||||||
|
* Upgrade deps by @aldas in https://github.com/labstack/echo/pull/2605
|
||||||
|
* Change type definition blocks to single declarations. This helps copy… by @aldas in https://github.com/labstack/echo/pull/2606
|
||||||
|
* Fix Real IP logic by @cl-bvl in https://github.com/labstack/echo/pull/2550
|
||||||
|
* Default binder can use `UnmarshalParams(params []string) error` inter… by @aldas in https://github.com/labstack/echo/pull/2607
|
||||||
|
* Default binder can bind pointer to slice as struct field. For example `*[]string` by @aldas in https://github.com/labstack/echo/pull/2608
|
||||||
|
* Remove maxparam dependence from Context by @aldas in https://github.com/labstack/echo/pull/2611
|
||||||
|
* When route is registered with empty path it is normalized to `/`. by @aldas in https://github.com/labstack/echo/pull/2616
|
||||||
|
* proxy middleware should use httputil.ReverseProxy for SSE requests by @aldas in https://github.com/labstack/echo/pull/2624
|
||||||
|
|
||||||
|
|
||||||
|
## v4.11.4 - 2023-12-20
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Upgrade golang.org/x/crypto to v0.17.0 to fix vulnerability [issue](https://pkg.go.dev/vuln/GO-2023-2402) [#2562](https://github.com/labstack/echo/pull/2562)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Update deps and mark Go version to 1.18 as this is what golang.org/x/* use [#2563](https://github.com/labstack/echo/pull/2563)
|
||||||
|
* Request logger: add example for Slog https://pkg.go.dev/log/slog [#2543](https://github.com/labstack/echo/pull/2543)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.11.3 - 2023-11-07
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* 'c.Attachment' and 'c.Inline' should escape filename in 'Content-Disposition' header to avoid 'Reflect File Download' vulnerability. [#2541](https://github.com/labstack/echo/pull/2541)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Tests: refactor context tests to be separate functions [#2540](https://github.com/labstack/echo/pull/2540)
|
||||||
|
* Proxy middleware: reuse echo request context [#2537](https://github.com/labstack/echo/pull/2537)
|
||||||
|
* Mark unmarshallable yaml struct tags as ignored [#2536](https://github.com/labstack/echo/pull/2536)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.11.2 - 2023-10-11
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Bump golang.org/x/net to prevent CVE-2023-39325 / CVE-2023-44487 HTTP/2 Rapid Reset Attack [#2527](https://github.com/labstack/echo/pull/2527)
|
||||||
|
* fix(sec): randomString bias introduced by #2490 [#2492](https://github.com/labstack/echo/pull/2492)
|
||||||
|
* CSRF/RequestID mw: switch math/random usage to crypto/random [#2490](https://github.com/labstack/echo/pull/2490)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Delete unused context in body_limit.go [#2483](https://github.com/labstack/echo/pull/2483)
|
||||||
|
* Use Go 1.21 in CI [#2505](https://github.com/labstack/echo/pull/2505)
|
||||||
|
* Fix some typos [#2511](https://github.com/labstack/echo/pull/2511)
|
||||||
|
* Allow CORS middleware to send Access-Control-Max-Age: 0 [#2518](https://github.com/labstack/echo/pull/2518)
|
||||||
|
* Bump dependancies [#2522](https://github.com/labstack/echo/pull/2522)
|
||||||
|
|
||||||
## v4.11.1 - 2023-07-16
|
## v4.11.1 - 2023-07-16
|
||||||
|
|
||||||
**Fixes**
|
**Fixes**
|
||||||
|
4
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
4
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
@ -31,6 +31,6 @@ benchmark: ## Run benchmarks
|
|||||||
help: ## Display this help screen
|
help: ## Display this help screen
|
||||||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
goversion ?= "1.17"
|
goversion ?= "1.19"
|
||||||
test_version: ## Run tests inside Docker with given version (defaults to 1.17 oldest supported). Example: make test_version goversion=1.17
|
test_version: ## Run tests inside Docker with given version (defaults to 1.19 oldest supported). Example: make test_version goversion=1.19
|
||||||
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
||||||
|
35
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
35
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
@ -3,26 +3,24 @@
|
|||||||
[![Sourcegraph](https://sourcegraph.com/github.com/labstack/echo/-/badge.svg?style=flat-square)](https://sourcegraph.com/github.com/labstack/echo?badge)
|
[![Sourcegraph](https://sourcegraph.com/github.com/labstack/echo/-/badge.svg?style=flat-square)](https://sourcegraph.com/github.com/labstack/echo?badge)
|
||||||
[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/labstack/echo/v4)
|
[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/labstack/echo/v4)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/labstack/echo?style=flat-square)](https://goreportcard.com/report/github.com/labstack/echo)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/labstack/echo?style=flat-square)](https://goreportcard.com/report/github.com/labstack/echo)
|
||||||
[![Build Status](http://img.shields.io/travis/labstack/echo.svg?style=flat-square)](https://travis-ci.org/labstack/echo)
|
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/labstack/echo/echo.yml?style=flat-square)](https://github.com/labstack/echo/actions)
|
||||||
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
|
[![Codecov](https://img.shields.io/codecov/c/github/labstack/echo.svg?style=flat-square)](https://codecov.io/gh/labstack/echo)
|
||||||
[![Forum](https://img.shields.io/badge/community-forum-00afd1.svg?style=flat-square)](https://github.com/labstack/echo/discussions)
|
[![Forum](https://img.shields.io/badge/community-forum-00afd1.svg?style=flat-square)](https://github.com/labstack/echo/discussions)
|
||||||
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
||||||
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
||||||
|
|
||||||
## Supported Go versions
|
## Echo
|
||||||
|
|
||||||
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with
|
High performance, extensible, minimalist Go web framework.
|
||||||
older versions.
|
|
||||||
|
|
||||||
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
* [Official website](https://echo.labstack.com)
|
||||||
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
* [Quick start](https://echo.labstack.com/docs/quick-start)
|
||||||
|
* [Middlewares](https://echo.labstack.com/docs/category/middleware)
|
||||||
|
|
||||||
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
Help and questions: [Github Discussions](https://github.com/labstack/echo/discussions)
|
||||||
way of using Echo going forward.
|
|
||||||
|
|
||||||
For older versions, please use the latest v3 tag.
|
|
||||||
|
|
||||||
## Feature Overview
|
### Feature Overview
|
||||||
|
|
||||||
- Optimized HTTP router which smartly prioritize routes
|
- Optimized HTTP router which smartly prioritize routes
|
||||||
- Build robust and scalable RESTful APIs
|
- Build robust and scalable RESTful APIs
|
||||||
@ -38,6 +36,18 @@ For older versions, please use the latest v3 tag.
|
|||||||
- Automatic TLS via Let’s Encrypt
|
- Automatic TLS via Let’s Encrypt
|
||||||
- HTTP/2 support
|
- HTTP/2 support
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="https://encore.dev" style="display: inline-flex; align-items: center; gap: 10px">
|
||||||
|
<img src="https://user-images.githubusercontent.com/78424526/214602214-52e0483a-b5fc-4d4c-b03e-0b7b23e012df.svg" height="28px" alt="encore icon"></img>
|
||||||
|
<b>Encore – the platform for building Go-based cloud backends</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Click [here](https://github.com/sponsors/labstack) for more information on sponsorship.
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
Date: 2020/11/11<br>
|
Date: 2020/11/11<br>
|
||||||
@ -57,6 +67,7 @@ The benchmarks above were run on an Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
|
|||||||
// go get github.com/labstack/echo/{version}
|
// go get github.com/labstack/echo/{version}
|
||||||
go get github.com/labstack/echo/v4
|
go get github.com/labstack/echo/v4
|
||||||
```
|
```
|
||||||
|
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with older versions.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@ -117,10 +128,6 @@ of middlewares in this list.
|
|||||||
|
|
||||||
Please send a PR to add your own library here.
|
Please send a PR to add your own library here.
|
||||||
|
|
||||||
## Help
|
|
||||||
|
|
||||||
- [Forum](https://github.com/labstack/echo/discussions)
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
**Use issues for everything**
|
**Use issues for everything**
|
||||||
|
124
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
124
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -11,23 +14,28 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Binder is the interface that wraps the Bind method.
|
// Binder is the interface that wraps the Bind method.
|
||||||
Binder interface {
|
type Binder interface {
|
||||||
Bind(i interface{}, c Context) error
|
Bind(i interface{}, c Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultBinder is the default implementation of the Binder interface.
|
// DefaultBinder is the default implementation of the Binder interface.
|
||||||
DefaultBinder struct{}
|
type DefaultBinder struct{}
|
||||||
|
|
||||||
// BindUnmarshaler is the interface used to wrap the UnmarshalParam method.
|
// BindUnmarshaler is the interface used to wrap the UnmarshalParam method.
|
||||||
// Types that don't implement this, but do implement encoding.TextUnmarshaler
|
// Types that don't implement this, but do implement encoding.TextUnmarshaler
|
||||||
// will use that interface instead.
|
// will use that interface instead.
|
||||||
BindUnmarshaler interface {
|
type BindUnmarshaler interface {
|
||||||
// UnmarshalParam decodes and assigns a value from an form or query param.
|
// UnmarshalParam decodes and assigns a value from an form or query param.
|
||||||
UnmarshalParam(param string) error
|
UnmarshalParam(param string) error
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
// bindMultipleUnmarshaler is used by binder to unmarshal multiple values from request at once to
|
||||||
|
// type implementing this interface. For example request could have multiple query fields `?a=1&a=2&b=test` in that case
|
||||||
|
// for `a` following slice `["1", "2"] will be passed to unmarshaller.
|
||||||
|
type bindMultipleUnmarshaler interface {
|
||||||
|
UnmarshalParams(params []string) error
|
||||||
|
}
|
||||||
|
|
||||||
// BindPathParams binds path params to bindable object
|
// BindPathParams binds path params to bindable object
|
||||||
func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
|
func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
|
||||||
@ -131,10 +139,29 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
typ := reflect.TypeOf(destination).Elem()
|
typ := reflect.TypeOf(destination).Elem()
|
||||||
val := reflect.ValueOf(destination).Elem()
|
val := reflect.ValueOf(destination).Elem()
|
||||||
|
|
||||||
// Map
|
// Support binding to limited Map destinations:
|
||||||
if typ.Kind() == reflect.Map {
|
// - map[string][]string,
|
||||||
|
// - map[string]string <-- (binds first value from data slice)
|
||||||
|
// - map[string]interface{}
|
||||||
|
// You are better off binding to struct but there are user who want this map feature. Source of data for these cases are:
|
||||||
|
// params,query,header,form as these sources produce string values, most of the time slice of strings, actually.
|
||||||
|
if typ.Kind() == reflect.Map && typ.Key().Kind() == reflect.String {
|
||||||
|
k := typ.Elem().Kind()
|
||||||
|
isElemInterface := k == reflect.Interface
|
||||||
|
isElemString := k == reflect.String
|
||||||
|
isElemSliceOfStrings := k == reflect.Slice && typ.Elem().Elem().Kind() == reflect.String
|
||||||
|
if !(isElemSliceOfStrings || isElemString || isElemInterface) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if val.IsNil() {
|
||||||
|
val.Set(reflect.MakeMap(typ))
|
||||||
|
}
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
|
if isElemString {
|
||||||
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
|
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
|
||||||
|
} else {
|
||||||
|
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -161,14 +188,14 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
}
|
}
|
||||||
structFieldKind := structField.Kind()
|
structFieldKind := structField.Kind()
|
||||||
inputFieldName := typeField.Tag.Get(tag)
|
inputFieldName := typeField.Tag.Get(tag)
|
||||||
if typeField.Anonymous && structField.Kind() == reflect.Struct && inputFieldName != "" {
|
if typeField.Anonymous && structFieldKind == reflect.Struct && inputFieldName != "" {
|
||||||
// if anonymous struct with query/param/form tags, report an error
|
// if anonymous struct with query/param/form tags, report an error
|
||||||
return errors.New("query/param/form tags are not allowed with anonymous struct field")
|
return errors.New("query/param/form tags are not allowed with anonymous struct field")
|
||||||
}
|
}
|
||||||
|
|
||||||
if inputFieldName == "" {
|
if inputFieldName == "" {
|
||||||
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
|
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
|
||||||
// structs that implement BindUnmarshaler are binded only when they have explicit tag
|
// structs that implement BindUnmarshaler are bound only when they have explicit tag
|
||||||
if _, ok := structField.Addr().Interface().(BindUnmarshaler); !ok && structFieldKind == reflect.Struct {
|
if _, ok := structField.Addr().Interface().(BindUnmarshaler); !ok && structFieldKind == reflect.Struct {
|
||||||
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
|
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -197,27 +224,46 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this first, in case we're dealing with an alias to an array type
|
// NOTE: algorithm here is not particularly sophisticated. It probably does not work with absurd types like `**[]*int`
|
||||||
if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok {
|
// but it is smart enough to handle niche cases like `*int`,`*[]string`,`[]*int` .
|
||||||
|
|
||||||
|
// try unmarshalling first, in case we're dealing with an alias to an array type
|
||||||
|
if ok, err := unmarshalInputsToField(typeField.Type.Kind(), inputValue, structField); ok {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
numElems := len(inputValue)
|
if ok, err := unmarshalInputToField(typeField.Type.Kind(), inputValue[0], structField); ok {
|
||||||
if structFieldKind == reflect.Slice && numElems > 0 {
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// we could be dealing with pointer to slice `*[]string` so dereference it. There are wierd OpenAPI generators
|
||||||
|
// that could create struct fields like that.
|
||||||
|
if structFieldKind == reflect.Pointer {
|
||||||
|
structFieldKind = structField.Elem().Kind()
|
||||||
|
structField = structField.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if structFieldKind == reflect.Slice {
|
||||||
sliceOf := structField.Type().Elem().Kind()
|
sliceOf := structField.Type().Elem().Kind()
|
||||||
|
numElems := len(inputValue)
|
||||||
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
||||||
for j := 0; j < numElems; j++ {
|
for j := 0; j < numElems; j++ {
|
||||||
if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil {
|
if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val.Field(i).Set(slice)
|
structField.Set(slice)
|
||||||
} else if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
|
continue
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
if err := setWithProperType(structFieldKind, inputValue[0], structField); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -225,7 +271,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
|
|
||||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
|
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
|
||||||
// But also call it here, in case we're dealing with an array of BindUnmarshalers
|
// But also call it here, in case we're dealing with an array of BindUnmarshalers
|
||||||
if ok, err := unmarshalField(valueKind, val, structField); ok {
|
if ok, err := unmarshalInputToField(valueKind, val, structField); ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,35 +312,41 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalField(valueKind reflect.Kind, val string, field reflect.Value) (bool, error) {
|
func unmarshalInputsToField(valueKind reflect.Kind, values []string, field reflect.Value) (bool, error) {
|
||||||
switch valueKind {
|
if valueKind == reflect.Ptr {
|
||||||
case reflect.Ptr:
|
if field.IsNil() {
|
||||||
return unmarshalFieldPtr(val, field)
|
field.Set(reflect.New(field.Type().Elem()))
|
||||||
default:
|
|
||||||
return unmarshalFieldNonPtr(val, field)
|
|
||||||
}
|
}
|
||||||
|
field = field.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalFieldNonPtr(value string, field reflect.Value) (bool, error) {
|
|
||||||
fieldIValue := field.Addr().Interface()
|
fieldIValue := field.Addr().Interface()
|
||||||
if unmarshaler, ok := fieldIValue.(BindUnmarshaler); ok {
|
unmarshaler, ok := fieldIValue.(bindMultipleUnmarshaler)
|
||||||
return true, unmarshaler.UnmarshalParam(value)
|
if !ok {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
if unmarshaler, ok := fieldIValue.(encoding.TextUnmarshaler); ok {
|
return true, unmarshaler.UnmarshalParams(values)
|
||||||
return true, unmarshaler.UnmarshalText([]byte(value))
|
}
|
||||||
|
|
||||||
|
func unmarshalInputToField(valueKind reflect.Kind, val string, field reflect.Value) (bool, error) {
|
||||||
|
if valueKind == reflect.Ptr {
|
||||||
|
if field.IsNil() {
|
||||||
|
field.Set(reflect.New(field.Type().Elem()))
|
||||||
|
}
|
||||||
|
field = field.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldIValue := field.Addr().Interface()
|
||||||
|
switch unmarshaler := fieldIValue.(type) {
|
||||||
|
case BindUnmarshaler:
|
||||||
|
return true, unmarshaler.UnmarshalParam(val)
|
||||||
|
case encoding.TextUnmarshaler:
|
||||||
|
return true, unmarshaler.UnmarshalText([]byte(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalFieldPtr(value string, field reflect.Value) (bool, error) {
|
|
||||||
if field.IsNil() {
|
|
||||||
// Initialize the pointer to a nil value
|
|
||||||
field.Set(reflect.New(field.Type().Elem()))
|
|
||||||
}
|
|
||||||
return unmarshalFieldNonPtr(value, field.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
func setIntField(value string, bitSize int, field reflect.Value) error {
|
func setIntField(value string, bitSize int, field reflect.Value) error {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
value = "0"
|
value = "0"
|
||||||
|
5
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
5
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -1323,7 +1326,7 @@ func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExi
|
|||||||
case time.Second:
|
case time.Second:
|
||||||
*dest = time.Unix(n, 0)
|
*dest = time.Unix(n, 0)
|
||||||
case time.Millisecond:
|
case time.Millisecond:
|
||||||
*dest = time.Unix(n/1e3, (n%1e3)*1e6) // TODO: time.UnixMilli(n) exists since Go1.17 switch to that when min version allows
|
*dest = time.UnixMilli(n)
|
||||||
case time.Nanosecond:
|
case time.Nanosecond:
|
||||||
*dest = time.Unix(0, n)
|
*dest = time.Unix(0, n)
|
||||||
}
|
}
|
||||||
|
57
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
57
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,10 +16,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Context represents the context of the current HTTP request. It holds request and
|
// Context represents the context of the current HTTP request. It holds request and
|
||||||
// response objects, path, path parameters, data and registered handler.
|
// response objects, path, path parameters, data and registered handler.
|
||||||
Context interface {
|
type Context interface {
|
||||||
// Request returns `*http.Request`.
|
// Request returns `*http.Request`.
|
||||||
Request() *http.Request
|
Request() *http.Request
|
||||||
|
|
||||||
@ -197,20 +199,33 @@ type (
|
|||||||
Reset(r *http.Request, w http.ResponseWriter)
|
Reset(r *http.Request, w http.ResponseWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
context struct {
|
type context struct {
|
||||||
request *http.Request
|
request *http.Request
|
||||||
response *Response
|
response *Response
|
||||||
path string
|
|
||||||
pnames []string
|
|
||||||
pvalues []string
|
|
||||||
query url.Values
|
query url.Values
|
||||||
handler HandlerFunc
|
|
||||||
store Map
|
|
||||||
echo *Echo
|
echo *Echo
|
||||||
logger Logger
|
logger Logger
|
||||||
|
|
||||||
|
store Map
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
|
// following fields are set by Router
|
||||||
|
|
||||||
|
// path is route path that Router matched. It is empty string where there is no route match.
|
||||||
|
// Route registered with RouteNotFound is considered as a match and path therefore is not empty.
|
||||||
|
path string
|
||||||
|
|
||||||
|
// pnames length is tied to param count for the matched route
|
||||||
|
pnames []string
|
||||||
|
|
||||||
|
// Usually echo.Echo is sizing pvalues but there could be user created middlewares that decide to
|
||||||
|
// overwrite parameter by calling SetParamNames + SetParamValues.
|
||||||
|
// When echo.Echo allocated that slice it length/capacity is tied to echo.Echo.maxParam value.
|
||||||
|
//
|
||||||
|
// It is important that pvalues size is always equal or bigger to pnames length.
|
||||||
|
pvalues []string
|
||||||
|
handler HandlerFunc
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
||||||
@ -329,13 +344,9 @@ func (c *context) SetParamNames(names ...string) {
|
|||||||
c.pnames = names
|
c.pnames = names
|
||||||
|
|
||||||
l := len(names)
|
l := len(names)
|
||||||
if *c.echo.maxParam < l {
|
|
||||||
*c.echo.maxParam = l
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.pvalues) < l {
|
if len(c.pvalues) < l {
|
||||||
// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
|
// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
|
||||||
// probably those values will be overriden in a Context#SetParamValues
|
// probably those values will be overridden in a Context#SetParamValues
|
||||||
newPvalues := make([]string, l)
|
newPvalues := make([]string, l)
|
||||||
copy(newPvalues, c.pvalues)
|
copy(newPvalues, c.pvalues)
|
||||||
c.pvalues = newPvalues
|
c.pvalues = newPvalues
|
||||||
@ -347,11 +358,11 @@ func (c *context) ParamValues() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) SetParamValues(values ...string) {
|
func (c *context) SetParamValues(values ...string) {
|
||||||
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam at all times
|
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam (or bigger) at all times
|
||||||
// It will brake the Router#Find code
|
// It will brake the Router#Find code
|
||||||
limit := len(values)
|
limit := len(values)
|
||||||
if limit > *c.echo.maxParam {
|
if limit > len(c.pvalues) {
|
||||||
limit = *c.echo.maxParam
|
c.pvalues = make([]string, limit)
|
||||||
}
|
}
|
||||||
for i := 0; i < limit; i++ {
|
for i := 0; i < limit; i++ {
|
||||||
c.pvalues[i] = values[i]
|
c.pvalues[i] = values[i]
|
||||||
@ -489,7 +500,7 @@ func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) json(code int, i interface{}, indent string) error {
|
func (c *context) json(code int, i interface{}, indent string) error {
|
||||||
c.writeContentType(MIMEApplicationJSONCharsetUTF8)
|
c.writeContentType(MIMEApplicationJSON)
|
||||||
c.response.Status = code
|
c.response.Status = code
|
||||||
return c.echo.JSONSerializer.Serialize(c, i, indent)
|
return c.echo.JSONSerializer.Serialize(c, i, indent)
|
||||||
}
|
}
|
||||||
@ -507,7 +518,7 @@ func (c *context) JSONPretty(code int, i interface{}, indent string) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) JSONBlob(code int, b []byte) (err error) {
|
func (c *context) JSONBlob(code int, b []byte) (err error) {
|
||||||
return c.Blob(code, MIMEApplicationJSONCharsetUTF8, b)
|
return c.Blob(code, MIMEApplicationJSON, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
||||||
@ -584,8 +595,10 @@ func (c *context) Inline(file, name string) error {
|
|||||||
return c.contentDisposition(file, name, "inline")
|
return c.contentDisposition(file, name, "inline")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
|
||||||
|
|
||||||
func (c *context) contentDisposition(file, name, dispositionType string) error {
|
func (c *context) contentDisposition(file, name, dispositionType string) error {
|
||||||
c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%q", dispositionType, name))
|
c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf(`%s; filename="%s"`, dispositionType, quoteEscaper.Replace(name)))
|
||||||
return c.File(file)
|
return c.File(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,8 +653,8 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
|
|||||||
c.path = ""
|
c.path = ""
|
||||||
c.pnames = nil
|
c.pnames = nil
|
||||||
c.logger = nil
|
c.logger = nil
|
||||||
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times
|
// NOTE: Don't reset because it has to have length c.echo.maxParam (or bigger) at all times
|
||||||
for i := 0; i < *c.echo.maxParam; i++ {
|
for i := 0; i < len(c.pvalues); i++ {
|
||||||
c.pvalues[i] = ""
|
c.pvalues[i] = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
53
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
53
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package echo implements high performance, minimalist Go web framework.
|
Package echo implements high performance, minimalist Go web framework.
|
||||||
|
|
||||||
@ -60,17 +63,16 @@ import (
|
|||||||
"golang.org/x/net/http2/h2c"
|
"golang.org/x/net/http2/h2c"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Echo is the top-level framework instance.
|
// Echo is the top-level framework instance.
|
||||||
//
|
//
|
||||||
// Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
|
// Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
|
||||||
// fields from handlers/middlewares and changing field values at the same time leads to data-races.
|
// fields from handlers/middlewares and changing field values at the same time leads to data-races.
|
||||||
// Adding new routes after the server has been started is also not safe!
|
// Adding new routes after the server has been started is also not safe!
|
||||||
Echo struct {
|
type Echo struct {
|
||||||
filesystem
|
filesystem
|
||||||
common
|
common
|
||||||
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
||||||
// listener address info (on which interface/port was listener binded) without having data races.
|
// listener address info (on which interface/port was listener bound) without having data races.
|
||||||
startupMutex sync.RWMutex
|
startupMutex sync.RWMutex
|
||||||
colorer *color.Color
|
colorer *color.Color
|
||||||
|
|
||||||
@ -107,50 +109,49 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Route contains a handler and information for matching against requests.
|
// Route contains a handler and information for matching against requests.
|
||||||
Route struct {
|
type Route struct {
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPError represents an error that occurred while handling a request.
|
// HTTPError represents an error that occurred while handling a request.
|
||||||
HTTPError struct {
|
type HTTPError struct {
|
||||||
Code int `json:"-"`
|
Code int `json:"-"`
|
||||||
Message interface{} `json:"message"`
|
Message interface{} `json:"message"`
|
||||||
Internal error `json:"-"` // Stores the error returned by an external dependency
|
Internal error `json:"-"` // Stores the error returned by an external dependency
|
||||||
}
|
}
|
||||||
|
|
||||||
// MiddlewareFunc defines a function to process middleware.
|
// MiddlewareFunc defines a function to process middleware.
|
||||||
MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
type MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
||||||
|
|
||||||
// HandlerFunc defines a function to serve HTTP requests.
|
// HandlerFunc defines a function to serve HTTP requests.
|
||||||
HandlerFunc func(c Context) error
|
type HandlerFunc func(c Context) error
|
||||||
|
|
||||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||||
HTTPErrorHandler func(err error, c Context)
|
type HTTPErrorHandler func(err error, c Context)
|
||||||
|
|
||||||
// Validator is the interface that wraps the Validate function.
|
// Validator is the interface that wraps the Validate function.
|
||||||
Validator interface {
|
type Validator interface {
|
||||||
Validate(i interface{}) error
|
Validate(i interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
|
// JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
|
||||||
JSONSerializer interface {
|
type JSONSerializer interface {
|
||||||
Serialize(c Context, i interface{}, indent string) error
|
Serialize(c Context, i interface{}, indent string) error
|
||||||
Deserialize(c Context, i interface{}) error
|
Deserialize(c Context, i interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderer is the interface that wraps the Render function.
|
// Renderer is the interface that wraps the Render function.
|
||||||
Renderer interface {
|
type Renderer interface {
|
||||||
Render(io.Writer, string, interface{}, Context) error
|
Render(io.Writer, string, interface{}, Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map defines a generic map of type `map[string]interface{}`.
|
// Map defines a generic map of type `map[string]interface{}`.
|
||||||
Map map[string]interface{}
|
type Map map[string]interface{}
|
||||||
|
|
||||||
// Common struct for Echo & Group.
|
// Common struct for Echo & Group.
|
||||||
common struct{}
|
type common struct{}
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP methods
|
// HTTP methods
|
||||||
// NOTE: Deprecated, please use the stdlib constants directly instead.
|
// NOTE: Deprecated, please use the stdlib constants directly instead.
|
||||||
@ -169,7 +170,12 @@ const (
|
|||||||
|
|
||||||
// MIME types
|
// MIME types
|
||||||
const (
|
const (
|
||||||
|
// MIMEApplicationJSON JavaScript Object Notation (JSON) https://www.rfc-editor.org/rfc/rfc8259
|
||||||
MIMEApplicationJSON = "application/json"
|
MIMEApplicationJSON = "application/json"
|
||||||
|
// Deprecated: Please use MIMEApplicationJSON instead. JSON should be encoded using UTF-8 by default.
|
||||||
|
// No "charset" parameter is defined for this registration.
|
||||||
|
// Adding one really has no effect on compliant recipients.
|
||||||
|
// See RFC 8259, section 8.1. https://datatracker.ietf.org/doc/html/rfc8259#section-8.1
|
||||||
MIMEApplicationJSONCharsetUTF8 = MIMEApplicationJSON + "; " + charsetUTF8
|
MIMEApplicationJSONCharsetUTF8 = MIMEApplicationJSON + "; " + charsetUTF8
|
||||||
MIMEApplicationJavaScript = "application/javascript"
|
MIMEApplicationJavaScript = "application/javascript"
|
||||||
MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
|
MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
|
||||||
@ -259,7 +265,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.11.1"
|
Version = "4.12.0"
|
||||||
website = "https://echo.labstack.com"
|
website = "https://echo.labstack.com"
|
||||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||||
banner = `
|
banner = `
|
||||||
@ -274,8 +280,7 @@ ____________________________________O/_______
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var methods = [...]string{
|
||||||
methods = [...]string{
|
|
||||||
http.MethodConnect,
|
http.MethodConnect,
|
||||||
http.MethodDelete,
|
http.MethodDelete,
|
||||||
http.MethodGet,
|
http.MethodGet,
|
||||||
@ -288,7 +293,6 @@ var (
|
|||||||
http.MethodTrace,
|
http.MethodTrace,
|
||||||
REPORT,
|
REPORT,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
var (
|
var (
|
||||||
@ -341,13 +345,15 @@ var (
|
|||||||
ErrInvalidListenerNetwork = errors.New("invalid listener network")
|
ErrInvalidListenerNetwork = errors.New("invalid listener network")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error handlers
|
// NotFoundHandler is the handler that router uses in case there was no matching route found. Returns an error that results
|
||||||
var (
|
// HTTP 404 status code.
|
||||||
NotFoundHandler = func(c Context) error {
|
var NotFoundHandler = func(c Context) error {
|
||||||
return ErrNotFound
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodNotAllowedHandler = func(c Context) error {
|
// MethodNotAllowedHandler is the handler thar router uses in case there was no matching route found but there was
|
||||||
|
// another matching routes for that requested URL. Returns an error that results HTTP 405 Method Not Allowed status code.
|
||||||
|
var MethodNotAllowedHandler = func(c Context) error {
|
||||||
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
||||||
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
||||||
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
||||||
@ -356,7 +362,6 @@ var (
|
|||||||
}
|
}
|
||||||
return ErrMethodNotAllowed
|
return ErrMethodNotAllowed
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// New creates an instance of Echo.
|
// New creates an instance of Echo.
|
||||||
func New() (e *Echo) {
|
func New() (e *Echo) {
|
||||||
@ -414,7 +419,7 @@ func (e *Echo) Routers() map[string]*Router {
|
|||||||
//
|
//
|
||||||
// NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error).
|
// NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error).
|
||||||
// When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from
|
// When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from
|
||||||
// handler. Then the error that global error handler received will be ignored because we have already "commited" the
|
// handler. Then the error that global error handler received will be ignored because we have already "committed" the
|
||||||
// response and status code header has been sent to the client.
|
// response and status code header has been sent to the client.
|
||||||
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
||||||
|
|
||||||
|
3
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
7
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
7
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
@ -1,21 +1,22 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Group is a set of sub-routes for a specified route. It can be used for inner
|
// Group is a set of sub-routes for a specified route. It can be used for inner
|
||||||
// routes that share a common middleware or functionality that should be separate
|
// routes that share a common middleware or functionality that should be separate
|
||||||
// from the parent echo instance while still inheriting from it.
|
// from the parent echo instance while still inheriting from it.
|
||||||
Group struct {
|
type Group struct {
|
||||||
common
|
common
|
||||||
host string
|
host string
|
||||||
prefix string
|
prefix string
|
||||||
middleware []MiddlewareFunc
|
middleware []MiddlewareFunc
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Use implements `Echo#Use()` for sub-routes within the Group.
|
// Use implements `Echo#Use()` for sub-routes within the Group.
|
||||||
func (g *Group) Use(middleware ...MiddlewareFunc) {
|
func (g *Group) Use(middleware ...MiddlewareFunc) {
|
||||||
|
3
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
17
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
17
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -64,7 +67,7 @@ XFF: "x" "x, a" "x, a, b"
|
|||||||
```
|
```
|
||||||
|
|
||||||
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
||||||
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructre".
|
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructure".
|
||||||
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
||||||
|
|
||||||
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
||||||
@ -225,15 +228,21 @@ func extractIP(req *http.Request) string {
|
|||||||
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||||
checker := newIPChecker(options)
|
checker := newIPChecker(options)
|
||||||
return func(req *http.Request) string {
|
return func(req *http.Request) string {
|
||||||
|
directIP := extractIP(req)
|
||||||
realIP := req.Header.Get(HeaderXRealIP)
|
realIP := req.Header.Get(HeaderXRealIP)
|
||||||
if realIP != "" {
|
if realIP == "" {
|
||||||
|
return directIP
|
||||||
|
}
|
||||||
|
|
||||||
|
if checker.trust(net.ParseIP(directIP)) {
|
||||||
realIP = strings.TrimPrefix(realIP, "[")
|
realIP = strings.TrimPrefix(realIP, "[")
|
||||||
realIP = strings.TrimSuffix(realIP, "]")
|
realIP = strings.TrimSuffix(realIP, "]")
|
||||||
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
if rIP := net.ParseIP(realIP); rIP != nil {
|
||||||
return realIP
|
return realIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return extractIP(req)
|
|
||||||
|
return directIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/github.com/labstack/echo/v4/json.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/json.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
10
vendor/github.com/labstack/echo/v4/log.go
generated
vendored
10
vendor/github.com/labstack/echo/v4/log.go
generated
vendored
@ -1,14 +1,15 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Logger defines the logging interface.
|
// Logger defines the logging interface.
|
||||||
Logger interface {
|
type Logger interface {
|
||||||
Output() io.Writer
|
Output() io.Writer
|
||||||
SetOutput(w io.Writer)
|
SetOutput(w io.Writer)
|
||||||
Prefix() string
|
Prefix() string
|
||||||
@ -38,4 +39,3 @@ type (
|
|||||||
Panicj(j log.JSON)
|
Panicj(j log.JSON)
|
||||||
Panicf(format string, args ...interface{})
|
Panicf(format string, args ...interface{})
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
15
vendor/github.com/labstack/echo/v4/middleware/basic_auth.go
generated
vendored
15
vendor/github.com/labstack/echo/v4/middleware/basic_auth.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,9 +12,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// BasicAuthConfig defines the config for BasicAuth middleware.
|
// BasicAuthConfig defines the config for BasicAuth middleware.
|
||||||
BasicAuthConfig struct {
|
type BasicAuthConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -25,21 +27,20 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BasicAuthValidator defines a function to validate BasicAuth credentials.
|
// BasicAuthValidator defines a function to validate BasicAuth credentials.
|
||||||
BasicAuthValidator func(string, string, echo.Context) (bool, error)
|
// The function should return a boolean indicating whether the credentials are valid,
|
||||||
)
|
// and an error if any error occurs during the validation process.
|
||||||
|
type BasicAuthValidator func(string, string, echo.Context) (bool, error)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
basic = "basic"
|
basic = "basic"
|
||||||
defaultRealm = "Restricted"
|
defaultRealm = "Restricted"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultBasicAuthConfig is the default BasicAuth middleware config.
|
// DefaultBasicAuthConfig is the default BasicAuth middleware config.
|
||||||
DefaultBasicAuthConfig = BasicAuthConfig{
|
var DefaultBasicAuthConfig = BasicAuthConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Realm: defaultRealm,
|
Realm: defaultRealm,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// BasicAuth returns an BasicAuth middleware.
|
// BasicAuth returns an BasicAuth middleware.
|
||||||
//
|
//
|
||||||
|
27
vendor/github.com/labstack/echo/v4/middleware/body_dump.go
generated
vendored
27
vendor/github.com/labstack/echo/v4/middleware/body_dump.go
generated
vendored
@ -1,8 +1,12 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -10,9 +14,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// BodyDumpConfig defines the config for BodyDump middleware.
|
// BodyDumpConfig defines the config for BodyDump middleware.
|
||||||
BodyDumpConfig struct {
|
type BodyDumpConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -22,20 +25,17 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BodyDumpHandler receives the request and response payload.
|
// BodyDumpHandler receives the request and response payload.
|
||||||
BodyDumpHandler func(echo.Context, []byte, []byte)
|
type BodyDumpHandler func(echo.Context, []byte, []byte)
|
||||||
|
|
||||||
bodyDumpResponseWriter struct {
|
type bodyDumpResponseWriter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultBodyDumpConfig is the default BodyDump middleware config.
|
// DefaultBodyDumpConfig is the default BodyDump middleware config.
|
||||||
DefaultBodyDumpConfig = BodyDumpConfig{
|
var DefaultBodyDumpConfig = BodyDumpConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// BodyDump returns a BodyDump middleware.
|
// BodyDump returns a BodyDump middleware.
|
||||||
//
|
//
|
||||||
@ -98,9 +98,16 @@ func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *bodyDumpResponseWriter) Flush() {
|
func (w *bodyDumpResponseWriter) Flush() {
|
||||||
w.ResponseWriter.(http.Flusher).Flush()
|
err := responseControllerFlush(w.ResponseWriter)
|
||||||
|
if err != nil && errors.Is(err, http.ErrNotSupported) {
|
||||||
|
panic(errors.New("response writer flushing is not supported"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return w.ResponseWriter.(http.Hijacker).Hijack()
|
return responseControllerHijack(w.ResponseWriter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *bodyDumpResponseWriter) Unwrap() http.ResponseWriter {
|
||||||
|
return w.ResponseWriter
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/labstack/echo/v4/middleware/body_limit.go
generated
vendored
19
vendor/github.com/labstack/echo/v4/middleware/body_limit.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,9 +12,8 @@ import (
|
|||||||
"github.com/labstack/gommon/bytes"
|
"github.com/labstack/gommon/bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// BodyLimitConfig defines the config for BodyLimit middleware.
|
// BodyLimitConfig defines the config for BodyLimit middleware.
|
||||||
BodyLimitConfig struct {
|
type BodyLimitConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -21,20 +23,16 @@ type (
|
|||||||
limit int64
|
limit int64
|
||||||
}
|
}
|
||||||
|
|
||||||
limitedReader struct {
|
type limitedReader struct {
|
||||||
BodyLimitConfig
|
BodyLimitConfig
|
||||||
reader io.ReadCloser
|
reader io.ReadCloser
|
||||||
read int64
|
read int64
|
||||||
context echo.Context
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultBodyLimitConfig is the default BodyLimit middleware config.
|
// DefaultBodyLimitConfig is the default BodyLimit middleware config.
|
||||||
DefaultBodyLimitConfig = BodyLimitConfig{
|
var DefaultBodyLimitConfig = BodyLimitConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// BodyLimit returns a BodyLimit middleware.
|
// BodyLimit returns a BodyLimit middleware.
|
||||||
//
|
//
|
||||||
@ -80,7 +78,7 @@ func BodyLimitWithConfig(config BodyLimitConfig) echo.MiddlewareFunc {
|
|||||||
|
|
||||||
// Based on content read
|
// Based on content read
|
||||||
r := pool.Get().(*limitedReader)
|
r := pool.Get().(*limitedReader)
|
||||||
r.Reset(req.Body, c)
|
r.Reset(req.Body)
|
||||||
defer pool.Put(r)
|
defer pool.Put(r)
|
||||||
req.Body = r
|
req.Body = r
|
||||||
|
|
||||||
@ -102,9 +100,8 @@ func (r *limitedReader) Close() error {
|
|||||||
return r.reader.Close()
|
return r.reader.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *limitedReader) Reset(reader io.ReadCloser, context echo.Context) {
|
func (r *limitedReader) Reset(reader io.ReadCloser) {
|
||||||
r.reader = reader
|
r.reader = reader
|
||||||
r.context = context
|
|
||||||
r.read = 0
|
r.read = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
vendor/github.com/labstack/echo/v4/middleware/compress.go
generated
vendored
21
vendor/github.com/labstack/echo/v4/middleware/compress.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,9 +16,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// GzipConfig defines the config for Gzip middleware.
|
// GzipConfig defines the config for Gzip middleware.
|
||||||
GzipConfig struct {
|
type GzipConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ type (
|
|||||||
MinLength int
|
MinLength int
|
||||||
}
|
}
|
||||||
|
|
||||||
gzipResponseWriter struct {
|
type gzipResponseWriter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
wroteHeader bool
|
wroteHeader bool
|
||||||
@ -47,20 +49,17 @@ type (
|
|||||||
buffer *bytes.Buffer
|
buffer *bytes.Buffer
|
||||||
code int
|
code int
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gzipScheme = "gzip"
|
gzipScheme = "gzip"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultGzipConfig is the default Gzip middleware config.
|
// DefaultGzipConfig is the default Gzip middleware config.
|
||||||
DefaultGzipConfig = GzipConfig{
|
var DefaultGzipConfig = GzipConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Level: -1,
|
Level: -1,
|
||||||
MinLength: 0,
|
MinLength: 0,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Gzip returns a middleware which compresses HTTP response using gzip compression
|
// Gzip returns a middleware which compresses HTTP response using gzip compression
|
||||||
// scheme.
|
// scheme.
|
||||||
@ -191,13 +190,15 @@ func (w *gzipResponseWriter) Flush() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.Writer.(*gzip.Writer).Flush()
|
w.Writer.(*gzip.Writer).Flush()
|
||||||
if flusher, ok := w.ResponseWriter.(http.Flusher); ok {
|
_ = responseControllerFlush(w.ResponseWriter)
|
||||||
flusher.Flush()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *gzipResponseWriter) Unwrap() http.ResponseWriter {
|
||||||
|
return w.ResponseWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return w.ResponseWriter.(http.Hijacker).Hijack()
|
return responseControllerHijack(w.ResponseWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *gzipResponseWriter) Push(target string, opts *http.PushOptions) error {
|
func (w *gzipResponseWriter) Push(target string, opts *http.PushOptions) error {
|
||||||
|
5
vendor/github.com/labstack/echo/v4/middleware/context_timeout.go
generated
vendored
5
vendor/github.com/labstack/echo/v4/middleware/context_timeout.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,7 +16,7 @@ type ContextTimeoutConfig struct {
|
|||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
// ErrorHandler is a function when error aries in middeware execution.
|
// ErrorHandler is a function when error aries in middleware execution.
|
||||||
ErrorHandler func(err error, c echo.Context) error
|
ErrorHandler func(err error, c echo.Context) error
|
||||||
|
|
||||||
// Timeout configures a timeout for the middleware, defaults to 0 for no timeout
|
// Timeout configures a timeout for the middleware, defaults to 0 for no timeout
|
||||||
|
24
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
24
vendor/github.com/labstack/echo/v4/middleware/cors.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,9 +12,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// CORSConfig defines the config for CORS middleware.
|
// CORSConfig defines the config for CORS middleware.
|
||||||
CORSConfig struct {
|
type CORSConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ type (
|
|||||||
// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
|
||||||
//
|
//
|
||||||
// Optional.
|
// Optional.
|
||||||
AllowOriginFunc func(origin string) (bool, error) `yaml:"allow_origin_func"`
|
AllowOriginFunc func(origin string) (bool, error) `yaml:"-"`
|
||||||
|
|
||||||
// AllowMethods determines the value of the Access-Control-Allow-Methods
|
// AllowMethods determines the value of the Access-Control-Allow-Methods
|
||||||
// response header. This header specified the list of methods allowed when
|
// response header. This header specified the list of methods allowed when
|
||||||
@ -99,22 +101,20 @@ type (
|
|||||||
// MaxAge determines the value of the Access-Control-Max-Age response header.
|
// MaxAge determines the value of the Access-Control-Max-Age response header.
|
||||||
// This header indicates how long (in seconds) the results of a preflight
|
// This header indicates how long (in seconds) the results of a preflight
|
||||||
// request can be cached.
|
// request can be cached.
|
||||||
|
// The header is set only if MaxAge != 0, negative value sends "0" which instructs browsers not to cache that response.
|
||||||
//
|
//
|
||||||
// Optional. Default value 0. The header is set only if MaxAge > 0.
|
// Optional. Default value 0 - meaning header is not sent.
|
||||||
//
|
//
|
||||||
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
||||||
MaxAge int `yaml:"max_age"`
|
MaxAge int `yaml:"max_age"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultCORSConfig is the default CORS middleware config.
|
// DefaultCORSConfig is the default CORS middleware config.
|
||||||
DefaultCORSConfig = CORSConfig{
|
var DefaultCORSConfig = CORSConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
AllowOrigins: []string{"*"},
|
AllowOrigins: []string{"*"},
|
||||||
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// CORS returns a Cross-Origin Resource Sharing (CORS) middleware.
|
// CORS returns a Cross-Origin Resource Sharing (CORS) middleware.
|
||||||
// See also [MDN: Cross-Origin Resource Sharing (CORS)].
|
// See also [MDN: Cross-Origin Resource Sharing (CORS)].
|
||||||
@ -159,7 +159,11 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
allowMethods := strings.Join(config.AllowMethods, ",")
|
allowMethods := strings.Join(config.AllowMethods, ",")
|
||||||
allowHeaders := strings.Join(config.AllowHeaders, ",")
|
allowHeaders := strings.Join(config.AllowHeaders, ",")
|
||||||
exposeHeaders := strings.Join(config.ExposeHeaders, ",")
|
exposeHeaders := strings.Join(config.ExposeHeaders, ",")
|
||||||
maxAge := strconv.Itoa(config.MaxAge)
|
|
||||||
|
maxAge := "0"
|
||||||
|
if config.MaxAge > 0 {
|
||||||
|
maxAge = strconv.Itoa(config.MaxAge)
|
||||||
|
}
|
||||||
|
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
@ -282,7 +286,7 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
|
|||||||
res.Header().Set(echo.HeaderAccessControlAllowHeaders, h)
|
res.Header().Set(echo.HeaderAccessControlAllowHeaders, h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config.MaxAge > 0 {
|
if config.MaxAge != 0 {
|
||||||
res.Header().Set(echo.HeaderAccessControlMaxAge, maxAge)
|
res.Header().Set(echo.HeaderAccessControlMaxAge, maxAge)
|
||||||
}
|
}
|
||||||
return c.NoContent(http.StatusNoContent)
|
return c.NoContent(http.StatusNoContent)
|
||||||
|
17
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
17
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,12 +9,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/gommon/random"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// CSRFConfig defines the config for CSRF middleware.
|
// CSRFConfig defines the config for CSRF middleware.
|
||||||
CSRFConfig struct {
|
type CSRFConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -67,15 +68,13 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CSRFErrorHandler is a function which is executed for creating custom errors.
|
// CSRFErrorHandler is a function which is executed for creating custom errors.
|
||||||
CSRFErrorHandler func(err error, c echo.Context) error
|
type CSRFErrorHandler func(err error, c echo.Context) error
|
||||||
)
|
|
||||||
|
|
||||||
// ErrCSRFInvalid is returned when CSRF check fails
|
// ErrCSRFInvalid is returned when CSRF check fails
|
||||||
var ErrCSRFInvalid = echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
var ErrCSRFInvalid = echo.NewHTTPError(http.StatusForbidden, "invalid csrf token")
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultCSRFConfig is the default CSRF middleware config.
|
// DefaultCSRFConfig is the default CSRF middleware config.
|
||||||
DefaultCSRFConfig = CSRFConfig{
|
var DefaultCSRFConfig = CSRFConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
TokenLength: 32,
|
TokenLength: 32,
|
||||||
TokenLookup: "header:" + echo.HeaderXCSRFToken,
|
TokenLookup: "header:" + echo.HeaderXCSRFToken,
|
||||||
@ -84,7 +83,6 @@ var (
|
|||||||
CookieMaxAge: 86400,
|
CookieMaxAge: 86400,
|
||||||
CookieSameSite: http.SameSiteDefaultMode,
|
CookieSameSite: http.SameSiteDefaultMode,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// CSRF returns a Cross-Site Request Forgery (CSRF) middleware.
|
// CSRF returns a Cross-Site Request Forgery (CSRF) middleware.
|
||||||
// See: https://en.wikipedia.org/wiki/Cross-site_request_forgery
|
// See: https://en.wikipedia.org/wiki/Cross-site_request_forgery
|
||||||
@ -103,6 +101,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
|||||||
if config.TokenLength == 0 {
|
if config.TokenLength == 0 {
|
||||||
config.TokenLength = DefaultCSRFConfig.TokenLength
|
config.TokenLength = DefaultCSRFConfig.TokenLength
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TokenLookup == "" {
|
if config.TokenLookup == "" {
|
||||||
config.TokenLookup = DefaultCSRFConfig.TokenLookup
|
config.TokenLookup = DefaultCSRFConfig.TokenLookup
|
||||||
}
|
}
|
||||||
@ -132,7 +131,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
|||||||
|
|
||||||
token := ""
|
token := ""
|
||||||
if k, err := c.Cookie(config.CookieName); err != nil {
|
if k, err := c.Cookie(config.CookieName); err != nil {
|
||||||
token = random.String(config.TokenLength) // Generate token
|
token = randomString(config.TokenLength)
|
||||||
} else {
|
} else {
|
||||||
token = k.Value // Reuse token
|
token = k.Value // Reuse token
|
||||||
}
|
}
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/decompress.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/decompress.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,16 +12,14 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// DecompressConfig defines the config for Decompress middleware.
|
// DecompressConfig defines the config for Decompress middleware.
|
||||||
DecompressConfig struct {
|
type DecompressConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
// GzipDecompressPool defines an interface to provide the sync.Pool used to create/store Gzip readers
|
// GzipDecompressPool defines an interface to provide the sync.Pool used to create/store Gzip readers
|
||||||
GzipDecompressPool Decompressor
|
GzipDecompressPool Decompressor
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// GZIPEncoding content-encoding header if set to "gzip", decompress body contents.
|
// GZIPEncoding content-encoding header if set to "gzip", decompress body contents.
|
||||||
const GZIPEncoding string = "gzip"
|
const GZIPEncoding string = "gzip"
|
||||||
@ -28,13 +29,11 @@ type Decompressor interface {
|
|||||||
gzipDecompressPool() sync.Pool
|
gzipDecompressPool() sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultDecompressConfig defines the config for decompress middleware
|
// DefaultDecompressConfig defines the config for decompress middleware
|
||||||
DefaultDecompressConfig = DecompressConfig{
|
var DefaultDecompressConfig = DecompressConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
GzipDecompressPool: &DefaultGzipDecompressPool{},
|
GzipDecompressPool: &DefaultGzipDecompressPool{},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultGzipDecompressPool is the default implementation of Decompressor interface
|
// DefaultGzipDecompressPool is the default implementation of Decompressor interface
|
||||||
type DefaultGzipDecompressPool struct {
|
type DefaultGzipDecompressPool struct {
|
||||||
|
3
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/extractor.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
27
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
27
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
//go:build go1.15
|
//go:build go1.15
|
||||||
// +build go1.15
|
// +build go1.15
|
||||||
|
|
||||||
@ -12,9 +15,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// JWTConfig defines the config for JWT middleware.
|
// JWTConfig defines the config for JWT middleware.
|
||||||
JWTConfig struct {
|
type JWTConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -112,29 +114,27 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JWTSuccessHandler defines a function which is executed for a valid token.
|
// JWTSuccessHandler defines a function which is executed for a valid token.
|
||||||
JWTSuccessHandler func(c echo.Context)
|
type JWTSuccessHandler func(c echo.Context)
|
||||||
|
|
||||||
// JWTErrorHandler defines a function which is executed for an invalid token.
|
// JWTErrorHandler defines a function which is executed for an invalid token.
|
||||||
JWTErrorHandler func(err error) error
|
type JWTErrorHandler func(err error) error
|
||||||
|
|
||||||
// JWTErrorHandlerWithContext is almost identical to JWTErrorHandler, but it's passed the current context.
|
// JWTErrorHandlerWithContext is almost identical to JWTErrorHandler, but it's passed the current context.
|
||||||
JWTErrorHandlerWithContext func(err error, c echo.Context) error
|
type JWTErrorHandlerWithContext func(err error, c echo.Context) error
|
||||||
)
|
|
||||||
|
|
||||||
// Algorithms
|
// Algorithms
|
||||||
const (
|
const (
|
||||||
AlgorithmHS256 = "HS256"
|
AlgorithmHS256 = "HS256"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Errors
|
// ErrJWTMissing is error that is returned when no JWToken was extracted from the request.
|
||||||
var (
|
var ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt")
|
||||||
ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt")
|
|
||||||
ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt")
|
// ErrJWTInvalid is error that is returned when middleware could not parse JWT correctly.
|
||||||
)
|
var ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt")
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultJWTConfig is the default JWT auth middleware config.
|
// DefaultJWTConfig is the default JWT auth middleware config.
|
||||||
DefaultJWTConfig = JWTConfig{
|
var DefaultJWTConfig = JWTConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
SigningMethod: AlgorithmHS256,
|
SigningMethod: AlgorithmHS256,
|
||||||
ContextKey: "user",
|
ContextKey: "user",
|
||||||
@ -144,7 +144,6 @@ var (
|
|||||||
Claims: jwt.MapClaims{},
|
Claims: jwt.MapClaims{},
|
||||||
KeyFunc: nil,
|
KeyFunc: nil,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// JWT returns a JSON Web Token (JWT) auth middleware.
|
// JWT returns a JSON Web Token (JWT) auth middleware.
|
||||||
//
|
//
|
||||||
|
27
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
27
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,9 +9,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// KeyAuthConfig defines the config for KeyAuth middleware.
|
// KeyAuthConfig defines the config for KeyAuth middleware.
|
||||||
KeyAuthConfig struct {
|
type KeyAuthConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -49,26 +51,23 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
||||||
KeyAuthValidator func(auth string, c echo.Context) (bool, error)
|
type KeyAuthValidator func(auth string, c echo.Context) (bool, error)
|
||||||
|
|
||||||
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
||||||
KeyAuthErrorHandler func(err error, c echo.Context) error
|
type KeyAuthErrorHandler func(err error, c echo.Context) error
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultKeyAuthConfig is the default KeyAuth middleware config.
|
|
||||||
DefaultKeyAuthConfig = KeyAuthConfig{
|
|
||||||
Skipper: DefaultSkipper,
|
|
||||||
KeyLookup: "header:" + echo.HeaderAuthorization,
|
|
||||||
AuthScheme: "Bearer",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrKeyAuthMissing is error type when KeyAuth middleware is unable to extract value from lookups
|
// ErrKeyAuthMissing is error type when KeyAuth middleware is unable to extract value from lookups
|
||||||
type ErrKeyAuthMissing struct {
|
type ErrKeyAuthMissing struct {
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultKeyAuthConfig is the default KeyAuth middleware config.
|
||||||
|
var DefaultKeyAuthConfig = KeyAuthConfig{
|
||||||
|
Skipper: DefaultSkipper,
|
||||||
|
KeyLookup: "header:" + echo.HeaderAuthorization,
|
||||||
|
AuthScheme: "Bearer",
|
||||||
|
}
|
||||||
|
|
||||||
// Error returns errors text
|
// Error returns errors text
|
||||||
func (e *ErrKeyAuthMissing) Error() string {
|
func (e *ErrKeyAuthMissing) Error() string {
|
||||||
return e.Err.Error()
|
return e.Err.Error()
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/logger.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/logger.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -14,9 +17,8 @@ import (
|
|||||||
"github.com/valyala/fasttemplate"
|
"github.com/valyala/fasttemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// LoggerConfig defines the config for Logger middleware.
|
// LoggerConfig defines the config for Logger middleware.
|
||||||
LoggerConfig struct {
|
type LoggerConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -71,11 +73,9 @@ type (
|
|||||||
colorer *color.Color
|
colorer *color.Color
|
||||||
pool *sync.Pool
|
pool *sync.Pool
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultLoggerConfig is the default Logger middleware config.
|
// DefaultLoggerConfig is the default Logger middleware config.
|
||||||
DefaultLoggerConfig = LoggerConfig{
|
var DefaultLoggerConfig = LoggerConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}",` +
|
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}",` +
|
||||||
`"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` +
|
`"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` +
|
||||||
@ -84,7 +84,6 @@ var (
|
|||||||
CustomTimeFormat: "2006-01-02 15:04:05.00000",
|
CustomTimeFormat: "2006-01-02 15:04:05.00000",
|
||||||
colorer: color.New(),
|
colorer: color.New(),
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Logger returns a middleware that logs HTTP requests.
|
// Logger returns a middleware that logs HTTP requests.
|
||||||
func Logger() echo.MiddlewareFunc {
|
func Logger() echo.MiddlewareFunc {
|
||||||
|
13
vendor/github.com/labstack/echo/v4/middleware/method_override.go
generated
vendored
13
vendor/github.com/labstack/echo/v4/middleware/method_override.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,9 +9,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// MethodOverrideConfig defines the config for MethodOverride middleware.
|
// MethodOverrideConfig defines the config for MethodOverride middleware.
|
||||||
MethodOverrideConfig struct {
|
type MethodOverrideConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -18,16 +20,13 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MethodOverrideGetter is a function that gets overridden method from the request
|
// MethodOverrideGetter is a function that gets overridden method from the request
|
||||||
MethodOverrideGetter func(echo.Context) string
|
type MethodOverrideGetter func(echo.Context) string
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultMethodOverrideConfig is the default MethodOverride middleware config.
|
// DefaultMethodOverrideConfig is the default MethodOverride middleware config.
|
||||||
DefaultMethodOverrideConfig = MethodOverrideConfig{
|
var DefaultMethodOverrideConfig = MethodOverrideConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Getter: MethodFromHeader(echo.HeaderXHTTPMethodOverride),
|
Getter: MethodFromHeader(echo.HeaderXHTTPMethodOverride),
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// MethodOverride returns a MethodOverride middleware.
|
// MethodOverride returns a MethodOverride middleware.
|
||||||
// MethodOverride middleware checks for the overridden method from the request and
|
// MethodOverride middleware checks for the overridden method from the request and
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/middleware.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,14 +12,12 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Skipper defines a function to skip middleware. Returning true skips processing
|
// Skipper defines a function to skip middleware. Returning true skips processing
|
||||||
// the middleware.
|
// the middleware.
|
||||||
Skipper func(c echo.Context) bool
|
type Skipper func(c echo.Context) bool
|
||||||
|
|
||||||
// BeforeFunc defines a function which is executed just before the middleware.
|
// BeforeFunc defines a function which is executed just before the middleware.
|
||||||
BeforeFunc func(c echo.Context)
|
type BeforeFunc func(c echo.Context)
|
||||||
)
|
|
||||||
|
|
||||||
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
|
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
|
||||||
groups := pattern.FindAllStringSubmatch(input, -1)
|
groups := pattern.FindAllStringSubmatch(input, -1)
|
||||||
@ -53,7 +54,7 @@ func rewriteURL(rewriteRegex map[*regexp.Regexp]string, req *http.Request) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depending how HTTP request is sent RequestURI could contain Scheme://Host/path or be just /path.
|
// Depending on how HTTP request is sent RequestURI could contain Scheme://Host/path or be just /path.
|
||||||
// We only want to use path part for rewriting and therefore trim prefix if it exists
|
// We only want to use path part for rewriting and therefore trim prefix if it exists
|
||||||
rawURI := req.RequestURI
|
rawURI := req.RequestURI
|
||||||
if rawURI != "" && rawURI[0] != '/' {
|
if rawURI != "" && rawURI[0] != '/' {
|
||||||
|
30
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
30
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -19,9 +22,8 @@ import (
|
|||||||
|
|
||||||
// TODO: Handle TLS proxy
|
// TODO: Handle TLS proxy
|
||||||
|
|
||||||
type (
|
|
||||||
// ProxyConfig defines the config for Proxy middleware.
|
// ProxyConfig defines the config for Proxy middleware.
|
||||||
ProxyConfig struct {
|
type ProxyConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -85,14 +87,14 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProxyTarget defines the upstream target.
|
// ProxyTarget defines the upstream target.
|
||||||
ProxyTarget struct {
|
type ProxyTarget struct {
|
||||||
Name string
|
Name string
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
Meta echo.Map
|
Meta echo.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyBalancer defines an interface to implement a load balancing technique.
|
// ProxyBalancer defines an interface to implement a load balancing technique.
|
||||||
ProxyBalancer interface {
|
type ProxyBalancer interface {
|
||||||
AddTarget(*ProxyTarget) bool
|
AddTarget(*ProxyTarget) bool
|
||||||
RemoveTarget(string) bool
|
RemoveTarget(string) bool
|
||||||
Next(echo.Context) *ProxyTarget
|
Next(echo.Context) *ProxyTarget
|
||||||
@ -100,36 +102,33 @@ type (
|
|||||||
|
|
||||||
// TargetProvider defines an interface that gives the opportunity for balancer
|
// TargetProvider defines an interface that gives the opportunity for balancer
|
||||||
// to return custom errors when selecting target.
|
// to return custom errors when selecting target.
|
||||||
TargetProvider interface {
|
type TargetProvider interface {
|
||||||
NextTarget(echo.Context) (*ProxyTarget, error)
|
NextTarget(echo.Context) (*ProxyTarget, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
commonBalancer struct {
|
type commonBalancer struct {
|
||||||
targets []*ProxyTarget
|
targets []*ProxyTarget
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomBalancer implements a random load balancing technique.
|
// RandomBalancer implements a random load balancing technique.
|
||||||
randomBalancer struct {
|
type randomBalancer struct {
|
||||||
commonBalancer
|
commonBalancer
|
||||||
random *rand.Rand
|
random *rand.Rand
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoundRobinBalancer implements a round-robin load balancing technique.
|
// RoundRobinBalancer implements a round-robin load balancing technique.
|
||||||
roundRobinBalancer struct {
|
type roundRobinBalancer struct {
|
||||||
commonBalancer
|
commonBalancer
|
||||||
// tracking the index on `targets` slice for the next `*ProxyTarget` to be used
|
// tracking the index on `targets` slice for the next `*ProxyTarget` to be used
|
||||||
i int
|
i int
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultProxyConfig is the default Proxy middleware config.
|
// DefaultProxyConfig is the default Proxy middleware config.
|
||||||
DefaultProxyConfig = ProxyConfig{
|
var DefaultProxyConfig = ProxyConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
ContextKey: "target",
|
ContextKey: "target",
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
|
func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -359,12 +358,15 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
|
|||||||
c.Set("_error", nil)
|
c.Set("_error", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is needed for ProxyConfig.ModifyResponse and/or ProxyConfig.Transport to be able to process the Request
|
||||||
|
// that Balancer may have replaced with c.SetRequest.
|
||||||
|
req = c.Request()
|
||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
switch {
|
switch {
|
||||||
case c.IsWebSocket():
|
case c.IsWebSocket():
|
||||||
proxyRaw(tgt, c).ServeHTTP(res, req)
|
proxyRaw(tgt, c).ServeHTTP(res, req)
|
||||||
case req.Header.Get(echo.HeaderAccept) == "text/event-stream":
|
default: // even SSE requests
|
||||||
default:
|
|
||||||
proxyHTTP(tgt, c, config).ServeHTTP(res, req)
|
proxyHTTP(tgt, c, config).ServeHTTP(res, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
generated
vendored
31
vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,17 +12,14 @@ import (
|
|||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// RateLimiterStore is the interface to be implemented by custom stores.
|
// RateLimiterStore is the interface to be implemented by custom stores.
|
||||||
RateLimiterStore interface {
|
type RateLimiterStore interface {
|
||||||
// Stores for the rate limiter have to implement the Allow method
|
// Stores for the rate limiter have to implement the Allow method
|
||||||
Allow(identifier string) (bool, error)
|
Allow(identifier string) (bool, error)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// RateLimiterConfig defines the configuration for the rate limiter
|
// RateLimiterConfig defines the configuration for the rate limiter
|
||||||
RateLimiterConfig struct {
|
type RateLimiterConfig struct {
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
BeforeFunc BeforeFunc
|
BeforeFunc BeforeFunc
|
||||||
// IdentifierExtractor uses echo.Context to extract the identifier for a visitor
|
// IdentifierExtractor uses echo.Context to extract the identifier for a visitor
|
||||||
@ -31,17 +31,15 @@ type (
|
|||||||
// DenyHandler provides a handler to be called when RateLimiter denies access
|
// DenyHandler provides a handler to be called when RateLimiter denies access
|
||||||
DenyHandler func(context echo.Context, identifier string, err error) error
|
DenyHandler func(context echo.Context, identifier string, err error) error
|
||||||
}
|
}
|
||||||
// Extractor is used to extract data from echo.Context
|
|
||||||
Extractor func(context echo.Context) (string, error)
|
|
||||||
)
|
|
||||||
|
|
||||||
// errors
|
// Extractor is used to extract data from echo.Context
|
||||||
var (
|
type Extractor func(context echo.Context) (string, error)
|
||||||
|
|
||||||
// ErrRateLimitExceeded denotes an error raised when rate limit is exceeded
|
// ErrRateLimitExceeded denotes an error raised when rate limit is exceeded
|
||||||
ErrRateLimitExceeded = echo.NewHTTPError(http.StatusTooManyRequests, "rate limit exceeded")
|
var ErrRateLimitExceeded = echo.NewHTTPError(http.StatusTooManyRequests, "rate limit exceeded")
|
||||||
|
|
||||||
// ErrExtractorError denotes an error raised when extractor function is unsuccessful
|
// ErrExtractorError denotes an error raised when extractor function is unsuccessful
|
||||||
ErrExtractorError = echo.NewHTTPError(http.StatusForbidden, "error while extracting identifier")
|
var ErrExtractorError = echo.NewHTTPError(http.StatusForbidden, "error while extracting identifier")
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultRateLimiterConfig defines default values for RateLimiterConfig
|
// DefaultRateLimiterConfig defines default values for RateLimiterConfig
|
||||||
var DefaultRateLimiterConfig = RateLimiterConfig{
|
var DefaultRateLimiterConfig = RateLimiterConfig{
|
||||||
@ -150,9 +148,8 @@ func RateLimiterWithConfig(config RateLimiterConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
|
||||||
// RateLimiterMemoryStore is the built-in store implementation for RateLimiter
|
// RateLimiterMemoryStore is the built-in store implementation for RateLimiter
|
||||||
RateLimiterMemoryStore struct {
|
type RateLimiterMemoryStore struct {
|
||||||
visitors map[string]*Visitor
|
visitors map[string]*Visitor
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
rate rate.Limit // for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
|
rate rate.Limit // for more info check out Limiter docs - https://pkg.go.dev/golang.org/x/time/rate#Limit.
|
||||||
@ -163,12 +160,12 @@ type (
|
|||||||
|
|
||||||
timeNow func() time.Time
|
timeNow func() time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visitor signifies a unique user's limiter details
|
// Visitor signifies a unique user's limiter details
|
||||||
Visitor struct {
|
type Visitor struct {
|
||||||
*rate.Limiter
|
*rate.Limiter
|
||||||
lastSeen time.Time
|
lastSeen time.Time
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
|
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
|
||||||
|
13
vendor/github.com/labstack/echo/v4/middleware/recover.go
generated
vendored
13
vendor/github.com/labstack/echo/v4/middleware/recover.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,12 +12,11 @@ import (
|
|||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// LogErrorFunc defines a function for custom logging in the middleware.
|
// LogErrorFunc defines a function for custom logging in the middleware.
|
||||||
LogErrorFunc func(c echo.Context, err error, stack []byte) error
|
type LogErrorFunc func(c echo.Context, err error, stack []byte) error
|
||||||
|
|
||||||
// RecoverConfig defines the config for Recover middleware.
|
// RecoverConfig defines the config for Recover middleware.
|
||||||
RecoverConfig struct {
|
type RecoverConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -45,11 +47,9 @@ type (
|
|||||||
// Optional. Default value false.
|
// Optional. Default value false.
|
||||||
DisableErrorHandler bool `yaml:"disable_error_handler"`
|
DisableErrorHandler bool `yaml:"disable_error_handler"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultRecoverConfig is the default Recover middleware config.
|
// DefaultRecoverConfig is the default Recover middleware config.
|
||||||
DefaultRecoverConfig = RecoverConfig{
|
var DefaultRecoverConfig = RecoverConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
StackSize: 4 << 10, // 4 KB
|
StackSize: 4 << 10, // 4 KB
|
||||||
DisableStackAll: false,
|
DisableStackAll: false,
|
||||||
@ -58,7 +58,6 @@ var (
|
|||||||
LogErrorFunc: nil,
|
LogErrorFunc: nil,
|
||||||
DisableErrorHandler: false,
|
DisableErrorHandler: false,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Recover returns a middleware which recovers from panics anywhere in the chain
|
// Recover returns a middleware which recovers from panics anywhere in the chain
|
||||||
// and handles the control to the centralized HTTPErrorHandler.
|
// and handles the control to the centralized HTTPErrorHandler.
|
||||||
|
3
vendor/github.com/labstack/echo/v4/middleware/redirect.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/redirect.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
16
vendor/github.com/labstack/echo/v4/middleware/request_id.go
generated
vendored
16
vendor/github.com/labstack/echo/v4/middleware/request_id.go
generated
vendored
@ -1,18 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/gommon/random"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// RequestIDConfig defines the config for RequestID middleware.
|
// RequestIDConfig defines the config for RequestID middleware.
|
||||||
RequestIDConfig struct {
|
type RequestIDConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
// Generator defines a function to generate an ID.
|
// Generator defines a function to generate an ID.
|
||||||
// Optional. Default value random.String(32).
|
// Optional. Defaults to generator for random string of length 32.
|
||||||
Generator func() string
|
Generator func() string
|
||||||
|
|
||||||
// RequestIDHandler defines a function which is executed for a request id.
|
// RequestIDHandler defines a function which is executed for a request id.
|
||||||
@ -21,16 +22,13 @@ type (
|
|||||||
// TargetHeader defines what header to look for to populate the id
|
// TargetHeader defines what header to look for to populate the id
|
||||||
TargetHeader string
|
TargetHeader string
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultRequestIDConfig is the default RequestID middleware config.
|
// DefaultRequestIDConfig is the default RequestID middleware config.
|
||||||
DefaultRequestIDConfig = RequestIDConfig{
|
var DefaultRequestIDConfig = RequestIDConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Generator: generator,
|
Generator: generator,
|
||||||
TargetHeader: echo.HeaderXRequestID,
|
TargetHeader: echo.HeaderXRequestID,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// RequestID returns a X-Request-ID middleware.
|
// RequestID returns a X-Request-ID middleware.
|
||||||
func RequestID() echo.MiddlewareFunc {
|
func RequestID() echo.MiddlewareFunc {
|
||||||
@ -73,5 +71,5 @@ func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generator() string {
|
func generator() string {
|
||||||
return random.String(32)
|
return randomString(32)
|
||||||
}
|
}
|
||||||
|
27
vendor/github.com/labstack/echo/v4/middleware/request_logger.go
generated
vendored
27
vendor/github.com/labstack/echo/v4/middleware/request_logger.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -8,6 +11,30 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Example for `slog` https://pkg.go.dev/log/slog
|
||||||
|
// logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||||
|
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
||||||
|
// LogStatus: true,
|
||||||
|
// LogURI: true,
|
||||||
|
// LogError: true,
|
||||||
|
// HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
|
||||||
|
// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
|
||||||
|
// if v.Error == nil {
|
||||||
|
// logger.LogAttrs(context.Background(), slog.LevelInfo, "REQUEST",
|
||||||
|
// slog.String("uri", v.URI),
|
||||||
|
// slog.Int("status", v.Status),
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// logger.LogAttrs(context.Background(), slog.LevelError, "REQUEST_ERROR",
|
||||||
|
// slog.String("uri", v.URI),
|
||||||
|
// slog.Int("status", v.Status),
|
||||||
|
// slog.String("err", v.Error.Error()),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
// },
|
||||||
|
// }))
|
||||||
|
//
|
||||||
// Example for `fmt.Printf`
|
// Example for `fmt.Printf`
|
||||||
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
||||||
// LogStatus: true,
|
// LogStatus: true,
|
||||||
|
44
vendor/github.com/labstack/echo/v4/middleware/responsecontroller_1.19.go
generated
vendored
Normal file
44
vendor/github.com/labstack/echo/v4/middleware/responsecontroller_1.19.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build !go1.20
|
||||||
|
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case interface{ FlushError() error }:
|
||||||
|
return t.FlushError()
|
||||||
|
case http.Flusher:
|
||||||
|
t.Flush()
|
||||||
|
return nil
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case http.Hijacker:
|
||||||
|
return t.Hijack()
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return nil, nil, fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
vendor/github.com/labstack/echo/v4/middleware/responsecontroller_1.20.go
generated
vendored
Normal file
20
vendor/github.com/labstack/echo/v4/middleware/responsecontroller_1.20.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build go1.20
|
||||||
|
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
return http.NewResponseController(rw).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
return http.NewResponseController(rw).Hijack()
|
||||||
|
}
|
13
vendor/github.com/labstack/echo/v4/middleware/rewrite.go
generated
vendored
13
vendor/github.com/labstack/echo/v4/middleware/rewrite.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,9 +9,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// RewriteConfig defines the config for Rewrite middleware.
|
// RewriteConfig defines the config for Rewrite middleware.
|
||||||
RewriteConfig struct {
|
type RewriteConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -27,16 +29,13 @@ type (
|
|||||||
// Example:
|
// Example:
|
||||||
// "^/old/[0.9]+/": "/new",
|
// "^/old/[0.9]+/": "/new",
|
||||||
// "^/api/.+?/(.*)": "/v2/$1",
|
// "^/api/.+?/(.*)": "/v2/$1",
|
||||||
RegexRules map[*regexp.Regexp]string `yaml:"regex_rules"`
|
RegexRules map[*regexp.Regexp]string `yaml:"-"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultRewriteConfig is the default Rewrite middleware config.
|
// DefaultRewriteConfig is the default Rewrite middleware config.
|
||||||
DefaultRewriteConfig = RewriteConfig{
|
var DefaultRewriteConfig = RewriteConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Rewrite returns a Rewrite middleware.
|
// Rewrite returns a Rewrite middleware.
|
||||||
//
|
//
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/secure.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/secure.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,9 +9,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// SecureConfig defines the config for Secure middleware.
|
// SecureConfig defines the config for Secure middleware.
|
||||||
SecureConfig struct {
|
type SecureConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -72,18 +74,15 @@ type (
|
|||||||
// Optional. Default value "".
|
// Optional. Default value "".
|
||||||
ReferrerPolicy string `yaml:"referrer_policy"`
|
ReferrerPolicy string `yaml:"referrer_policy"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultSecureConfig is the default Secure middleware config.
|
// DefaultSecureConfig is the default Secure middleware config.
|
||||||
DefaultSecureConfig = SecureConfig{
|
var DefaultSecureConfig = SecureConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
XSSProtection: "1; mode=block",
|
XSSProtection: "1; mode=block",
|
||||||
ContentTypeNosniff: "nosniff",
|
ContentTypeNosniff: "nosniff",
|
||||||
XFrameOptions: "SAMEORIGIN",
|
XFrameOptions: "SAMEORIGIN",
|
||||||
HSTSPreloadEnabled: false,
|
HSTSPreloadEnabled: false,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Secure returns a Secure middleware.
|
// Secure returns a Secure middleware.
|
||||||
// Secure middleware provides protection against cross-site scripting (XSS) attack,
|
// Secure middleware provides protection against cross-site scripting (XSS) attack,
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/slash.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/slash.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,9 +9,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// TrailingSlashConfig defines the config for TrailingSlash middleware.
|
// TrailingSlashConfig defines the config for TrailingSlash middleware.
|
||||||
TrailingSlashConfig struct {
|
type TrailingSlashConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -16,14 +18,11 @@ type (
|
|||||||
// Optional, but when provided the request is redirected using this code.
|
// Optional, but when provided the request is redirected using this code.
|
||||||
RedirectCode int `yaml:"redirect_code"`
|
RedirectCode int `yaml:"redirect_code"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultTrailingSlashConfig is the default TrailingSlash middleware config.
|
// DefaultTrailingSlashConfig is the default TrailingSlash middleware config.
|
||||||
DefaultTrailingSlashConfig = TrailingSlashConfig{
|
var DefaultTrailingSlashConfig = TrailingSlashConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// AddTrailingSlash returns a root level (before router) middleware which adds a
|
// AddTrailingSlash returns a root level (before router) middleware which adds a
|
||||||
// trailing slash to the request `URL#Path`.
|
// trailing slash to the request `URL#Path`.
|
||||||
|
11
vendor/github.com/labstack/echo/v4/middleware/static.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/static.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -14,9 +17,8 @@ import (
|
|||||||
"github.com/labstack/gommon/bytes"
|
"github.com/labstack/gommon/bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// StaticConfig defines the config for Static middleware.
|
// StaticConfig defines the config for Static middleware.
|
||||||
StaticConfig struct {
|
type StaticConfig struct {
|
||||||
// Skipper defines a function to skip middleware.
|
// Skipper defines a function to skip middleware.
|
||||||
Skipper Skipper
|
Skipper Skipper
|
||||||
|
|
||||||
@ -47,7 +49,6 @@ type (
|
|||||||
// Optional. Defaults to http.Dir(config.Root)
|
// Optional. Defaults to http.Dir(config.Root)
|
||||||
Filesystem http.FileSystem `yaml:"-"`
|
Filesystem http.FileSystem `yaml:"-"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -121,13 +122,11 @@ const html = `
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultStaticConfig is the default Static middleware config.
|
// DefaultStaticConfig is the default Static middleware config.
|
||||||
DefaultStaticConfig = StaticConfig{
|
var DefaultStaticConfig = StaticConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Index: "index.html",
|
Index: "index.html",
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Static returns a Static middleware to serves static content from the provided
|
// Static returns a Static middleware to serves static content from the provided
|
||||||
// root directory.
|
// root directory.
|
||||||
|
3
vendor/github.com/labstack/echo/v4/middleware/static_other.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/static_other.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
//go:build !windows
|
//go:build !windows
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
3
vendor/github.com/labstack/echo/v4/middleware/static_windows.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/middleware/static_windows.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
7
vendor/github.com/labstack/echo/v4/middleware/timeout.go
generated
vendored
7
vendor/github.com/labstack/echo/v4/middleware/timeout.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -77,14 +80,12 @@ type TimeoutConfig struct {
|
|||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultTimeoutConfig is the default Timeout middleware config.
|
// DefaultTimeoutConfig is the default Timeout middleware config.
|
||||||
DefaultTimeoutConfig = TimeoutConfig{
|
var DefaultTimeoutConfig = TimeoutConfig{
|
||||||
Skipper: DefaultSkipper,
|
Skipper: DefaultSkipper,
|
||||||
Timeout: 0,
|
Timeout: 0,
|
||||||
ErrorMessage: "",
|
ErrorMessage: "",
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Timeout returns a middleware which returns error (503 Service Unavailable error) to client immediately when handler
|
// Timeout returns a middleware which returns error (503 Service Unavailable error) to client immediately when handler
|
||||||
// call runs for longer than its time limit. NB: timeout does not stop handler execution.
|
// call runs for longer than its time limit. NB: timeout does not stop handler execution.
|
||||||
|
49
vendor/github.com/labstack/echo/v4/middleware/util.go
generated
vendored
49
vendor/github.com/labstack/echo/v4/middleware/util.go
generated
vendored
@ -1,7 +1,14 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/rand"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func matchScheme(domain, pattern string) bool {
|
func matchScheme(domain, pattern string) bool {
|
||||||
@ -52,3 +59,45 @@ func matchSubdomain(domain, pattern string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://tip.golang.org/doc/go1.19#:~:text=Read%20no%20longer%20buffers%20random%20data%20obtained%20from%20the%20operating%20system%20between%20calls
|
||||||
|
var randomReaderPool = sync.Pool{New: func() interface{} {
|
||||||
|
return bufio.NewReader(rand.Reader)
|
||||||
|
}}
|
||||||
|
|
||||||
|
const randomStringCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
const randomStringCharsetLen = 52 // len(randomStringCharset)
|
||||||
|
const randomStringMaxByte = 255 - (256 % randomStringCharsetLen)
|
||||||
|
|
||||||
|
func randomString(length uint8) string {
|
||||||
|
reader := randomReaderPool.Get().(*bufio.Reader)
|
||||||
|
defer randomReaderPool.Put(reader)
|
||||||
|
|
||||||
|
b := make([]byte, length)
|
||||||
|
r := make([]byte, length+(length/4)) // perf: avoid read from rand.Reader many times
|
||||||
|
var i uint8 = 0
|
||||||
|
|
||||||
|
// security note:
|
||||||
|
// we can't just simply do b[i]=randomStringCharset[rb%len(randomStringCharset)],
|
||||||
|
// len(len(randomStringCharset)) is 52, and rb is [0, 255], 256 = 52 * 4 + 48.
|
||||||
|
// make the first 48 characters more possibly to be generated then others.
|
||||||
|
// So we have to skip bytes when rb > randomStringMaxByte
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err := io.ReadFull(reader, r)
|
||||||
|
if err != nil {
|
||||||
|
panic("unexpected error happened when reading from bufio.NewReader(crypto/rand.Reader)")
|
||||||
|
}
|
||||||
|
for _, rb := range r {
|
||||||
|
if rb > randomStringMaxByte {
|
||||||
|
// Skip this number to avoid bias.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b[i] = randomStringCharset[rb%randomStringCharsetLen]
|
||||||
|
i++
|
||||||
|
if i == length {
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
15
vendor/github.com/labstack/echo/v4/response.go
generated
vendored
15
vendor/github.com/labstack/echo/v4/response.go
generated
vendored
@ -1,16 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Response wraps an http.ResponseWriter and implements its interface to be used
|
// Response wraps an http.ResponseWriter and implements its interface to be used
|
||||||
// by an HTTP handler to construct an HTTP response.
|
// by an HTTP handler to construct an HTTP response.
|
||||||
// See: https://golang.org/pkg/net/http/#ResponseWriter
|
// See: https://golang.org/pkg/net/http/#ResponseWriter
|
||||||
Response struct {
|
type Response struct {
|
||||||
echo *Echo
|
echo *Echo
|
||||||
beforeFuncs []func()
|
beforeFuncs []func()
|
||||||
afterFuncs []func()
|
afterFuncs []func()
|
||||||
@ -19,7 +22,6 @@ type (
|
|||||||
Size int64
|
Size int64
|
||||||
Committed bool
|
Committed bool
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// NewResponse creates a new instance of Response.
|
// NewResponse creates a new instance of Response.
|
||||||
func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) {
|
func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) {
|
||||||
@ -84,14 +86,17 @@ func (r *Response) Write(b []byte) (n int, err error) {
|
|||||||
// buffered data to the client.
|
// buffered data to the client.
|
||||||
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
|
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
|
||||||
func (r *Response) Flush() {
|
func (r *Response) Flush() {
|
||||||
r.Writer.(http.Flusher).Flush()
|
err := responseControllerFlush(r.Writer)
|
||||||
|
if err != nil && errors.Is(err, http.ErrNotSupported) {
|
||||||
|
panic(errors.New("response writer flushing is not supported"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack implements the http.Hijacker interface to allow an HTTP handler to
|
// Hijack implements the http.Hijacker interface to allow an HTTP handler to
|
||||||
// take over the connection.
|
// take over the connection.
|
||||||
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
|
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
|
||||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return r.Writer.(http.Hijacker).Hijack()
|
return responseControllerHijack(r.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns the original http.ResponseWriter.
|
// Unwrap returns the original http.ResponseWriter.
|
||||||
|
44
vendor/github.com/labstack/echo/v4/responsecontroller_1.19.go
generated
vendored
Normal file
44
vendor/github.com/labstack/echo/v4/responsecontroller_1.19.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build !go1.20
|
||||||
|
|
||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case interface{ FlushError() error }:
|
||||||
|
return t.FlushError()
|
||||||
|
case http.Flusher:
|
||||||
|
t.Flush()
|
||||||
|
return nil
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case http.Hijacker:
|
||||||
|
return t.Hijack()
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return nil, nil, fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
vendor/github.com/labstack/echo/v4/responsecontroller_1.20.go
generated
vendored
Normal file
20
vendor/github.com/labstack/echo/v4/responsecontroller_1.20.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build go1.20
|
||||||
|
|
||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
return http.NewResponseController(rw).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
return http.NewResponseController(rw).Hijack()
|
||||||
|
}
|
57
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
57
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,15 +9,15 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
// Router is the registry of all registered routes for an `Echo` instance for
|
// Router is the registry of all registered routes for an `Echo` instance for
|
||||||
// request matching and URL path parameter parsing.
|
// request matching and URL path parameter parsing.
|
||||||
Router struct {
|
type Router struct {
|
||||||
tree *node
|
tree *node
|
||||||
routes map[string]*Route
|
routes map[string]*Route
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
node struct {
|
|
||||||
|
type node struct {
|
||||||
kind kind
|
kind kind
|
||||||
label byte
|
label byte
|
||||||
prefix string
|
prefix string
|
||||||
@ -33,14 +36,17 @@ type (
|
|||||||
// notFoundHandler is handler registered with RouteNotFound method and is executed for 404 cases
|
// notFoundHandler is handler registered with RouteNotFound method and is executed for 404 cases
|
||||||
notFoundHandler *routeMethod
|
notFoundHandler *routeMethod
|
||||||
}
|
}
|
||||||
kind uint8
|
|
||||||
children []*node
|
type kind uint8
|
||||||
routeMethod struct {
|
type children []*node
|
||||||
|
|
||||||
|
type routeMethod struct {
|
||||||
ppath string
|
ppath string
|
||||||
pnames []string
|
pnames []string
|
||||||
handler HandlerFunc
|
handler HandlerFunc
|
||||||
}
|
}
|
||||||
routeMethods struct {
|
|
||||||
|
type routeMethods struct {
|
||||||
connect *routeMethod
|
connect *routeMethod
|
||||||
delete *routeMethod
|
delete *routeMethod
|
||||||
get *routeMethod
|
get *routeMethod
|
||||||
@ -55,7 +61,6 @@ type (
|
|||||||
anyOther map[string]*routeMethod
|
anyOther map[string]*routeMethod
|
||||||
allowHeader string
|
allowHeader string
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
staticKind kind = iota
|
staticKind kind = iota
|
||||||
@ -180,8 +185,18 @@ func (r *Router) Reverse(name string, params ...interface{}) string {
|
|||||||
return uri.String()
|
return uri.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizePathSlash(path string) string {
|
||||||
|
if path == "" {
|
||||||
|
path = "/"
|
||||||
|
} else if path[0] != '/' {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
||||||
r.Add(method, path, h)
|
path = normalizePathSlash(path)
|
||||||
|
r.insert(method, path, h)
|
||||||
|
|
||||||
route := &Route{
|
route := &Route{
|
||||||
Method: method,
|
Method: method,
|
||||||
@ -194,13 +209,11 @@ func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
|||||||
|
|
||||||
// Add registers a new route for method and path with matching handler.
|
// Add registers a new route for method and path with matching handler.
|
||||||
func (r *Router) Add(method, path string, h HandlerFunc) {
|
func (r *Router) Add(method, path string, h HandlerFunc) {
|
||||||
// Validate path
|
r.insert(method, normalizePathSlash(path), h)
|
||||||
if path == "" {
|
|
||||||
path = "/"
|
|
||||||
}
|
|
||||||
if path[0] != '/' {
|
|
||||||
path = "/" + path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) insert(method, path string, h HandlerFunc) {
|
||||||
|
path = normalizePathSlash(path)
|
||||||
pnames := []string{} // Param names
|
pnames := []string{} // Param names
|
||||||
ppath := path // Pristine path
|
ppath := path // Pristine path
|
||||||
|
|
||||||
@ -219,7 +232,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
}
|
}
|
||||||
j := i + 1
|
j := i + 1
|
||||||
|
|
||||||
r.insert(method, path[:i], staticKind, routeMethod{})
|
r.insertNode(method, path[:i], staticKind, routeMethod{})
|
||||||
for ; i < lcpIndex && path[i] != '/'; i++ {
|
for ; i < lcpIndex && path[i] != '/'; i++ {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,21 +242,21 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
|
|
||||||
if i == lcpIndex {
|
if i == lcpIndex {
|
||||||
// path node is last fragment of route path. ie. `/users/:id`
|
// path node is last fragment of route path. ie. `/users/:id`
|
||||||
r.insert(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
|
||||||
} else {
|
} else {
|
||||||
r.insert(method, path[:i], paramKind, routeMethod{})
|
r.insertNode(method, path[:i], paramKind, routeMethod{})
|
||||||
}
|
}
|
||||||
} else if path[i] == '*' {
|
} else if path[i] == '*' {
|
||||||
r.insert(method, path[:i], staticKind, routeMethod{})
|
r.insertNode(method, path[:i], staticKind, routeMethod{})
|
||||||
pnames = append(pnames, "*")
|
pnames = append(pnames, "*")
|
||||||
r.insert(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.insert(method, path, staticKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path, staticKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) insert(method, path string, t kind, rm routeMethod) {
|
func (r *Router) insertNode(method, path string, t kind, rm routeMethod) {
|
||||||
// Adjust max param
|
// Adjust max param
|
||||||
paramLen := len(rm.pnames)
|
paramLen := len(rm.pnames)
|
||||||
if *r.echo.maxParam < paramLen {
|
if *r.echo.maxParam < paramLen {
|
||||||
|
48
vendor/github.com/labstack/gommon/random/random.go
generated
vendored
48
vendor/github.com/labstack/gommon/random/random.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
package random
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
Random struct {
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Charsets
|
|
||||||
const (
|
|
||||||
Uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
Lowercase = "abcdefghijklmnopqrstuvwxyz"
|
|
||||||
Alphabetic = Uppercase + Lowercase
|
|
||||||
Numeric = "0123456789"
|
|
||||||
Alphanumeric = Alphabetic + Numeric
|
|
||||||
Symbols = "`" + `~!@#$%^&*()-_+={}[]|\;:"<>,./?`
|
|
||||||
Hex = Numeric + "abcdef"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
global = New()
|
|
||||||
)
|
|
||||||
|
|
||||||
func New() *Random {
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
return new(Random)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Random) String(length uint8, charsets ...string) string {
|
|
||||||
charset := strings.Join(charsets, "")
|
|
||||||
if charset == "" {
|
|
||||||
charset = Alphanumeric
|
|
||||||
}
|
|
||||||
b := make([]byte, length)
|
|
||||||
for i := range b {
|
|
||||||
b[i] = charset[rand.Int63()%int64(len(charset))]
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func String(length uint8, charsets ...string) string {
|
|
||||||
return global.String(length, charsets...)
|
|
||||||
}
|
|
4
vendor/github.com/likexian/gokit/LICENSE
generated
vendored
4
vendor/github.com/likexian/gokit/LICENSE
generated
vendored
@ -186,7 +186,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2012-2023 Li Kexian
|
Copyright 2012-2024 Li Kexian
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -200,6 +200,6 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
APPENDIX: Copyright 2012-2023 Li Kexian
|
APPENDIX: Copyright 2012-2024 Li Kexian
|
||||||
|
|
||||||
https://www.likexian.com/
|
https://www.likexian.com/
|
||||||
|
2
vendor/github.com/likexian/gokit/assert/README.md
generated
vendored
2
vendor/github.com/likexian/gokit/assert/README.md
generated
vendored
@ -85,7 +85,7 @@ b := assert.If(a == 1, true, false)
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2012-2023 [Li Kexian](https://www.likexian.com/)
|
Copyright 2012-2024 [Li Kexian](https://www.likexian.com/)
|
||||||
|
|
||||||
Licensed under the Apache License 2.0
|
Licensed under the Apache License 2.0
|
||||||
|
|
||||||
|
2
vendor/github.com/likexian/gokit/assert/assert.go
generated
vendored
2
vendor/github.com/likexian/gokit/assert/assert.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 Li Kexian
|
* Copyright 2012-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
2
vendor/github.com/likexian/gokit/assert/values.go
generated
vendored
2
vendor/github.com/likexian/gokit/assert/values.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 Li Kexian
|
* Copyright 2012-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
2
vendor/github.com/likexian/gokit/xrand/README.md
generated
vendored
2
vendor/github.com/likexian/gokit/xrand/README.md
generated
vendored
@ -43,7 +43,7 @@ if err != nil {
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2012-2023 [Li Kexian](https://www.likexian.com/)
|
Copyright 2012-2024 [Li Kexian](https://www.likexian.com/)
|
||||||
|
|
||||||
Licensed under the Apache License 2.0
|
Licensed under the Apache License 2.0
|
||||||
|
|
||||||
|
2
vendor/github.com/likexian/gokit/xrand/xrand.go
generated
vendored
2
vendor/github.com/likexian/gokit/xrand/xrand.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 Li Kexian
|
* Copyright 2012-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
2
vendor/github.com/likexian/gokit/xslice/README.md
generated
vendored
2
vendor/github.com/likexian/gokit/xslice/README.md
generated
vendored
@ -34,7 +34,7 @@ fmt.Println("new array:", array)
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2012-2023 [Li Kexian](https://www.likexian.com/)
|
Copyright 2012-2024 [Li Kexian](https://www.likexian.com/)
|
||||||
|
|
||||||
Licensed under the Apache License 2.0
|
Licensed under the Apache License 2.0
|
||||||
|
|
||||||
|
2
vendor/github.com/likexian/gokit/xslice/xslice.go
generated
vendored
2
vendor/github.com/likexian/gokit/xslice/xslice.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 Li Kexian
|
* Copyright 2012-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
4
vendor/github.com/likexian/whois-parser/LICENSE
generated
vendored
4
vendor/github.com/likexian/whois-parser/LICENSE
generated
vendored
@ -186,7 +186,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2014-2023 Li Kexian
|
Copyright 2014-2024 Li Kexian
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -200,6 +200,6 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
APPENDIX: Copyright 2014-2023 Li Kexian
|
APPENDIX: Copyright 2014-2024 Li Kexian
|
||||||
|
|
||||||
https://www.likexian.com/
|
https://www.likexian.com/
|
||||||
|
2
vendor/github.com/likexian/whois-parser/README.md
generated
vendored
2
vendor/github.com/likexian/whois-parser/README.md
generated
vendored
@ -71,7 +71,7 @@ Please refer to [whois](https://github.com/likexian/whois)
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2014-2023 [Li Kexian](https://www.likexian.com/)
|
Copyright 2014-2024 [Li Kexian](https://www.likexian.com/)
|
||||||
|
|
||||||
Licensed under the Apache License 2.0
|
Licensed under the Apache License 2.0
|
||||||
|
|
||||||
|
2
vendor/github.com/likexian/whois-parser/error.go
generated
vendored
2
vendor/github.com/likexian/whois-parser/error.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
4
vendor/github.com/likexian/whois-parser/parser.go
generated
vendored
4
vendor/github.com/likexian/whois-parser/parser.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -153,6 +153,8 @@ func Parse(text string) (whoisInfo WhoisInfo, err error) { //nolint:cyclop
|
|||||||
if !strings.Contains(name, " ") {
|
if !strings.Contains(name, " ") {
|
||||||
if name == "registrar" {
|
if name == "registrar" {
|
||||||
name += " name"
|
name += " name"
|
||||||
|
} else if domain.Extension == "dk" {
|
||||||
|
name = "registrant " + name
|
||||||
} else {
|
} else {
|
||||||
name += " organization"
|
name += " organization"
|
||||||
}
|
}
|
||||||
|
105
vendor/github.com/likexian/whois-parser/prepare.go
generated
vendored
105
vendor/github.com/likexian/whois-parser/prepare.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -91,6 +91,8 @@ func Prepare(text, ext string) (string, bool) { //nolint:cyclop
|
|||||||
return prepareBY(text), true
|
return prepareBY(text), true
|
||||||
case "ua":
|
case "ua":
|
||||||
return prepareUA(text), true
|
return prepareUA(text), true
|
||||||
|
case "at":
|
||||||
|
return prepareAT(text), true
|
||||||
default:
|
default:
|
||||||
return text, false
|
return text, false
|
||||||
}
|
}
|
||||||
@ -685,7 +687,7 @@ func prepareRU(text string) string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
var prepareJPreplacerRx = regexp.MustCompile(`\n\[(.+?)\][\ ]*(.+?)?`)
|
var prepareJPreplacerRx = regexp.MustCompile(`\n(?:\w+\.\s)?\[(.+?)\][\ ]*(.+?)?`)
|
||||||
|
|
||||||
// prepareJP do prepare the .jp domain
|
// prepareJP do prepare the .jp domain
|
||||||
func prepareJP(text string) string {
|
func prepareJP(text string) string {
|
||||||
@ -712,6 +714,7 @@ func prepareJP(text string) string {
|
|||||||
if strings.ToLower(token) == "registrant" {
|
if strings.ToLower(token) == "registrant" {
|
||||||
v = fmt.Sprintf("registrant name: %s", vs[1])
|
v = fmt.Sprintf("registrant name: %s", vs[1])
|
||||||
}
|
}
|
||||||
|
v = prepareSecondLevelJP(v, token, vs[1])
|
||||||
} else {
|
} else {
|
||||||
if token == addressToken {
|
if token == addressToken {
|
||||||
result += ", " + v
|
result += ", " + v
|
||||||
@ -724,6 +727,29 @@ func prepareJP(text string) string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareJP prepares specific mappings for second level .jp domains
|
||||||
|
// examples include:
|
||||||
|
// - co.jp
|
||||||
|
// - ac.jp
|
||||||
|
// - go.jp
|
||||||
|
// - or.jp
|
||||||
|
// - ad.jp
|
||||||
|
// - ne.jp
|
||||||
|
// - gr.jp
|
||||||
|
// - ed.jp
|
||||||
|
func prepareSecondLevelJP(original string, token string, value string) string {
|
||||||
|
if strings.ToLower(token) == "administrative contact" {
|
||||||
|
return fmt.Sprintf("Administrative Contact ID: %s", strings.TrimSpace(value))
|
||||||
|
}
|
||||||
|
if strings.ToLower(token) == "technical contact" {
|
||||||
|
return fmt.Sprintf("Technical Contact ID: %s", strings.TrimSpace(value))
|
||||||
|
}
|
||||||
|
if strings.ToLower(token) == "organization" || strings.ToLower(token) == "network service name" {
|
||||||
|
return fmt.Sprintf("Registrant Organization: %s", strings.TrimSpace(value))
|
||||||
|
}
|
||||||
|
return original
|
||||||
|
}
|
||||||
|
|
||||||
// prepareUK do prepare the .uk domain
|
// prepareUK do prepare the .uk domain
|
||||||
func prepareUK(text string) string {
|
func prepareUK(text string) string {
|
||||||
tokens := map[string]string{
|
tokens := map[string]string{
|
||||||
@ -1335,3 +1361,78 @@ func prepareUA(text string) string {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareAT prepares the .at domain
|
||||||
|
func prepareAT(text string) string {
|
||||||
|
result := ""
|
||||||
|
registrantID := ""
|
||||||
|
techID := ""
|
||||||
|
|
||||||
|
tokens := map[string]string{
|
||||||
|
"street address": "address",
|
||||||
|
"postal code": "address",
|
||||||
|
"city": "address",
|
||||||
|
"country": "address",
|
||||||
|
"e-mail": "email",
|
||||||
|
"nic-hdl": "id",
|
||||||
|
"personname": "name",
|
||||||
|
}
|
||||||
|
|
||||||
|
formatLine := func(line, token string) string {
|
||||||
|
before, after, _ := strings.Cut(line, ":")
|
||||||
|
key := strings.TrimSpace(before)
|
||||||
|
if t, ok := tokens[key]; ok {
|
||||||
|
key = t
|
||||||
|
}
|
||||||
|
val := strings.TrimSpace(after)
|
||||||
|
return fmt.Sprintf("%s %s: %s", token, key, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range strings.Split(text, "\n\n") {
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
if strings.HasPrefix(v, "%") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(v, ":") {
|
||||||
|
b := strings.Split(v, "\n")
|
||||||
|
if strings.HasPrefix(b[0], "domain") {
|
||||||
|
for _, l := range b {
|
||||||
|
w := ""
|
||||||
|
if before, after, ok := strings.Cut(l, ":"); ok {
|
||||||
|
key := strings.TrimSpace(before)
|
||||||
|
val := strings.TrimSpace(after)
|
||||||
|
switch key {
|
||||||
|
case "domain":
|
||||||
|
w = fmt.Sprintf("%s: %s", "domain name", val)
|
||||||
|
case "registrant":
|
||||||
|
registrantID = val
|
||||||
|
case "tech-c":
|
||||||
|
techID = val
|
||||||
|
case "changed":
|
||||||
|
w = fmt.Sprintf("%s: %s", "updated_date", val)
|
||||||
|
case "nserver":
|
||||||
|
w = fmt.Sprintf("%s: %s", "name_servers", val)
|
||||||
|
default:
|
||||||
|
w = fmt.Sprintf("domain %s: %s", key, val)
|
||||||
|
}
|
||||||
|
if w != "" {
|
||||||
|
result += w + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(b[0], "personname") {
|
||||||
|
token := ""
|
||||||
|
if strings.Contains(v, registrantID) {
|
||||||
|
token = "registrant"
|
||||||
|
} else if strings.Contains(v, techID) {
|
||||||
|
token = "technical contact"
|
||||||
|
}
|
||||||
|
for _, l := range strings.Split(v, "\n") {
|
||||||
|
result += formatLine(l, token) + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
4
vendor/github.com/likexian/whois-parser/rule.go
generated
vendored
4
vendor/github.com/likexian/whois-parser/rule.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -153,6 +153,8 @@ var (
|
|||||||
"registrant zipcode": "registrant_postal_code",
|
"registrant zipcode": "registrant_postal_code",
|
||||||
"registrant zip code": "registrant_postal_code",
|
"registrant zip code": "registrant_postal_code",
|
||||||
"registrant postalcode": "registrant_postal_code",
|
"registrant postalcode": "registrant_postal_code",
|
||||||
|
"registrant postal code": "registrant_postal_code",
|
||||||
|
"registrant contact postalcode": "registrant_postal_code",
|
||||||
"registrant contact postal code": "registrant_postal_code",
|
"registrant contact postal code": "registrant_postal_code",
|
||||||
"registrant country": "registrant_country",
|
"registrant country": "registrant_country",
|
||||||
"registrant country economy": "registrant_country",
|
"registrant country economy": "registrant_country",
|
||||||
|
2
vendor/github.com/likexian/whois-parser/struct.go
generated
vendored
2
vendor/github.com/likexian/whois-parser/struct.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
19
vendor/github.com/likexian/whois-parser/util.go
generated
vendored
19
vendor/github.com/likexian/whois-parser/util.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 Li Kexian
|
* Copyright 2014-2024 Li Kexian
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -118,16 +118,20 @@ func keys(m map[string]string) []string {
|
|||||||
// parseDateString attempts to parse a given date using a collection of common
|
// parseDateString attempts to parse a given date using a collection of common
|
||||||
// format strings. Date formats containing time components are tried first
|
// format strings. Date formats containing time components are tried first
|
||||||
// before attempts are made using date-only formats.
|
// before attempts are made using date-only formats.
|
||||||
func parseDateString(dateString string) (time.Time, error) {
|
func parseDateString(datetime string) (time.Time, error) {
|
||||||
formats := [...]string{
|
datetime = strings.Trim(datetime, ".")
|
||||||
|
datetime = strings.ReplaceAll(datetime, ". ", "-")
|
||||||
|
|
||||||
|
formats := [...]string{
|
||||||
// Date & time formats
|
// Date & time formats
|
||||||
"2006-01-02 15:04:05",
|
"2006-01-02 15:04:05",
|
||||||
|
"2006.01.02 15:04:05",
|
||||||
"02/01/2006 15:04:05",
|
"02/01/2006 15:04:05",
|
||||||
"02.01.2006 15:04:05",
|
"02.01.2006 15:04:05",
|
||||||
"02.1.2006 15:04:05",
|
"02.1.2006 15:04:05",
|
||||||
"2.1.2006 15:04:05",
|
"2.1.2006 15:04:05",
|
||||||
"02-Jan-2006 15:04:05",
|
"02-Jan-2006 15:04:05",
|
||||||
|
"20060102 15:04:05",
|
||||||
time.ANSIC,
|
time.ANSIC,
|
||||||
time.Stamp,
|
time.Stamp,
|
||||||
time.StampMilli,
|
time.StampMilli,
|
||||||
@ -151,24 +155,25 @@ func parseDateString(dateString string) (time.Time, error) {
|
|||||||
|
|
||||||
// Date only formats
|
// Date only formats
|
||||||
"2006-01-02",
|
"2006-01-02",
|
||||||
"2006. 01. 02.",
|
|
||||||
"02-Jan-2006",
|
"02-Jan-2006",
|
||||||
"02.01.2006",
|
"02.01.2006",
|
||||||
"02-01-2006",
|
"02-01-2006",
|
||||||
"January _2 2006",
|
"January _2 2006",
|
||||||
|
"Mon Jan _2 2006",
|
||||||
"02/01/2006",
|
"02/01/2006",
|
||||||
"01/02/2006",
|
"01/02/2006",
|
||||||
|
"2006/01/02",
|
||||||
"2006-Jan-02",
|
"2006-Jan-02",
|
||||||
"2006-Jan-02.",
|
"before Jan-2006",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
result, err := time.Parse(format, dateString)
|
result, err := time.Parse(format, datetime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return time.Now(), fmt.Errorf("could not parse %s as a date", dateString)
|
return time.Now(), fmt.Errorf("could not parse %s as a date", datetime)
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/likexian/whois/whois.go
generated
vendored
2
vendor/github.com/likexian/whois/whois.go
generated
vendored
@ -55,7 +55,7 @@ type Client struct {
|
|||||||
|
|
||||||
// Version returns package version
|
// Version returns package version
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return "1.15.0"
|
return "1.15.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Author returns package author
|
// Author returns package author
|
||||||
|
3
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
3
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine
|
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine && !tinygo
|
||||||
// +build darwin freebsd openbsd netbsd dragonfly hurd
|
// +build darwin freebsd openbsd netbsd dragonfly hurd
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
// +build !tinygo
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
|
5
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
5
vendor/github.com/mattn/go-isatty/isatty_others.go
generated
vendored
@ -1,5 +1,6 @@
|
|||||||
//go:build appengine || js || nacl || wasm
|
//go:build (appengine || js || nacl || tinygo || wasm) && !windows
|
||||||
// +build appengine js nacl wasm
|
// +build appengine js nacl tinygo wasm
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
|
3
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
3
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
//go:build (linux || aix || zos) && !appengine
|
//go:build (linux || aix || zos) && !appengine && !tinygo
|
||||||
// +build linux aix zos
|
// +build linux aix zos
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
// +build !tinygo
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/crypto/acme/version_go112.go
generated
vendored
1
vendor/golang.org/x/crypto/acme/version_go112.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.12
|
//go:build go1.12
|
||||||
// +build go1.12
|
|
||||||
|
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
|
57
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
57
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
@ -20,42 +20,45 @@ import (
|
|||||||
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
||||||
// improved enough that we can instead allocate chunks like this:
|
// improved enough that we can instead allocate chunks like this:
|
||||||
// make([]byte, max(16<<10, expectedBytesRemaining))
|
// make([]byte, max(16<<10, expectedBytesRemaining))
|
||||||
var (
|
var dataChunkPools = [...]sync.Pool{
|
||||||
dataChunkSizeClasses = []int{
|
{New: func() interface{} { return new([1 << 10]byte) }},
|
||||||
1 << 10,
|
{New: func() interface{} { return new([2 << 10]byte) }},
|
||||||
2 << 10,
|
{New: func() interface{} { return new([4 << 10]byte) }},
|
||||||
4 << 10,
|
{New: func() interface{} { return new([8 << 10]byte) }},
|
||||||
8 << 10,
|
{New: func() interface{} { return new([16 << 10]byte) }},
|
||||||
16 << 10,
|
|
||||||
}
|
}
|
||||||
dataChunkPools = [...]sync.Pool{
|
|
||||||
{New: func() interface{} { return make([]byte, 1<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 2<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 4<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 8<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 16<<10) }},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func getDataBufferChunk(size int64) []byte {
|
func getDataBufferChunk(size int64) []byte {
|
||||||
i := 0
|
switch {
|
||||||
for ; i < len(dataChunkSizeClasses)-1; i++ {
|
case size <= 1<<10:
|
||||||
if size <= int64(dataChunkSizeClasses[i]) {
|
return dataChunkPools[0].Get().(*[1 << 10]byte)[:]
|
||||||
break
|
case size <= 2<<10:
|
||||||
|
return dataChunkPools[1].Get().(*[2 << 10]byte)[:]
|
||||||
|
case size <= 4<<10:
|
||||||
|
return dataChunkPools[2].Get().(*[4 << 10]byte)[:]
|
||||||
|
case size <= 8<<10:
|
||||||
|
return dataChunkPools[3].Get().(*[8 << 10]byte)[:]
|
||||||
|
default:
|
||||||
|
return dataChunkPools[4].Get().(*[16 << 10]byte)[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dataChunkPools[i].Get().([]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
func putDataBufferChunk(p []byte) {
|
func putDataBufferChunk(p []byte) {
|
||||||
for i, n := range dataChunkSizeClasses {
|
switch len(p) {
|
||||||
if len(p) == n {
|
case 1 << 10:
|
||||||
dataChunkPools[i].Put(p)
|
dataChunkPools[0].Put((*[1 << 10]byte)(p))
|
||||||
return
|
case 2 << 10:
|
||||||
}
|
dataChunkPools[1].Put((*[2 << 10]byte)(p))
|
||||||
}
|
case 4 << 10:
|
||||||
|
dataChunkPools[2].Put((*[4 << 10]byte)(p))
|
||||||
|
case 8 << 10:
|
||||||
|
dataChunkPools[3].Put((*[8 << 10]byte)(p))
|
||||||
|
case 16 << 10:
|
||||||
|
dataChunkPools[4].Put((*[16 << 10]byte)(p))
|
||||||
|
default:
|
||||||
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
||||||
// Each dataBuffer is used to read DATA frames on a single stream.
|
// Each dataBuffer is used to read DATA frames on a single stream.
|
||||||
|
42
vendor/golang.org/x/net/http2/frame.go
generated
vendored
42
vendor/golang.org/x/net/http2/frame.go
generated
vendored
@ -1510,14 +1510,13 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fr *Framer) maxHeaderStringLen() int {
|
func (fr *Framer) maxHeaderStringLen() int {
|
||||||
v := fr.maxHeaderListSize()
|
v := int(fr.maxHeaderListSize())
|
||||||
if uint32(int(v)) == v {
|
if v < 0 {
|
||||||
return int(v)
|
// If maxHeaderListSize overflows an int, use no limit (0).
|
||||||
}
|
|
||||||
// They had a crazy big number for MaxHeaderBytes anyway,
|
|
||||||
// so give them unlimited header lengths:
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
||||||
// merge them into the provided hf and returns a MetaHeadersFrame
|
// merge them into the provided hf and returns a MetaHeadersFrame
|
||||||
@ -1565,6 +1564,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
if size > remainSize {
|
if size > remainSize {
|
||||||
hdec.SetEmitEnabled(false)
|
hdec.SetEmitEnabled(false)
|
||||||
mh.Truncated = true
|
mh.Truncated = true
|
||||||
|
remainSize = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remainSize -= size
|
remainSize -= size
|
||||||
@ -1577,6 +1577,36 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
var hc headersOrContinuation = hf
|
var hc headersOrContinuation = hf
|
||||||
for {
|
for {
|
||||||
frag := hc.HeaderBlockFragment()
|
frag := hc.HeaderBlockFragment()
|
||||||
|
|
||||||
|
// Avoid parsing large amounts of headers that we will then discard.
|
||||||
|
// If the sender exceeds the max header list size by too much,
|
||||||
|
// skip parsing the fragment and close the connection.
|
||||||
|
//
|
||||||
|
// "Too much" is either any CONTINUATION frame after we've already
|
||||||
|
// exceeded the max header list size (in which case remainSize is 0),
|
||||||
|
// or a frame whose encoded size is more than twice the remaining
|
||||||
|
// header list bytes we're willing to accept.
|
||||||
|
if int64(len(frag)) > int64(2*remainSize) {
|
||||||
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: header list too large")
|
||||||
|
}
|
||||||
|
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||||
|
// but the structure of the server's frame writer makes this difficult.
|
||||||
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also close the connection after any CONTINUATION frame following an
|
||||||
|
// invalid header, since we stop tracking the size of the headers after
|
||||||
|
// an invalid one.
|
||||||
|
if invalid != nil {
|
||||||
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: invalid header: %v", invalid)
|
||||||
|
}
|
||||||
|
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||||
|
// but the structure of the server's frame writer makes this difficult.
|
||||||
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := hdec.Write(frag); err != nil {
|
if _, err := hdec.Write(frag); err != nil {
|
||||||
return nil, ConnectionError(ErrCodeCompression)
|
return nil, ConnectionError(ErrCodeCompression)
|
||||||
}
|
}
|
||||||
|
30
vendor/golang.org/x/net/http2/go111.go
generated
vendored
30
vendor/golang.org/x/net/http2/go111.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.11
|
|
||||||
// +build go1.11
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptrace"
|
|
||||||
"net/textproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
|
||||||
return trace != nil && trace.WroteHeaderField != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
|
||||||
if trace != nil && trace.WroteHeaderField != nil {
|
|
||||||
trace.WroteHeaderField(k, []string{v})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
|
||||||
if trace != nil {
|
|
||||||
return trace.Got1xxResponse
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
27
vendor/golang.org/x/net/http2/go115.go
generated
vendored
27
vendor/golang.org/x/net/http2/go115.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.15
|
|
||||||
// +build go1.15
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
|
|
||||||
// connection.
|
|
||||||
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
|
||||||
dialer := &tls.Dialer{
|
|
||||||
Config: cfg,
|
|
||||||
}
|
|
||||||
cn, err := dialer.DialContext(ctx, network, addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
|
|
||||||
return tlsCn, nil
|
|
||||||
}
|
|
17
vendor/golang.org/x/net/http2/go118.go
generated
vendored
17
vendor/golang.org/x/net/http2/go118.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func tlsUnderlyingConn(tc *tls.Conn) net.Conn {
|
|
||||||
return tc.NetConn()
|
|
||||||
}
|
|
21
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
21
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.11
|
|
||||||
// +build !go1.11
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptrace"
|
|
||||||
"net/textproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
|
|
||||||
|
|
||||||
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
|
|
||||||
|
|
||||||
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
31
vendor/golang.org/x/net/http2/not_go115.go
generated
vendored
31
vendor/golang.org/x/net/http2/not_go115.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.15
|
|
||||||
// +build !go1.15
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dialTLSWithContext opens a TLS connection.
|
|
||||||
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
|
||||||
cn, err := tls.Dial(network, addr, cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := cn.Handshake(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if cfg.InsecureSkipVerify {
|
|
||||||
return cn, nil
|
|
||||||
}
|
|
||||||
if err := cn.VerifyHostname(cfg.ServerName); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cn, nil
|
|
||||||
}
|
|
17
vendor/golang.org/x/net/http2/not_go118.go
generated
vendored
17
vendor/golang.org/x/net/http2/not_go118.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func tlsUnderlyingConn(tc *tls.Conn) net.Conn {
|
|
||||||
return nil
|
|
||||||
}
|
|
11
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
11
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
@ -77,7 +77,10 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errClosedPipeWrite = errors.New("write on closed buffer")
|
var (
|
||||||
|
errClosedPipeWrite = errors.New("write on closed buffer")
|
||||||
|
errUninitializedPipeWrite = errors.New("write on uninitialized buffer")
|
||||||
|
)
|
||||||
|
|
||||||
// Write copies bytes from p into the buffer and wakes a reader.
|
// Write copies bytes from p into the buffer and wakes a reader.
|
||||||
// It is an error to write more data than the buffer can hold.
|
// It is an error to write more data than the buffer can hold.
|
||||||
@ -91,6 +94,12 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
|||||||
if p.err != nil || p.breakErr != nil {
|
if p.err != nil || p.breakErr != nil {
|
||||||
return 0, errClosedPipeWrite
|
return 0, errClosedPipeWrite
|
||||||
}
|
}
|
||||||
|
// pipe.setBuffer is never invoked, leaving the buffer uninitialized.
|
||||||
|
// We shouldn't try to write to an uninitialized pipe,
|
||||||
|
// but returning an error is better than panicking.
|
||||||
|
if p.b == nil {
|
||||||
|
return 0, errUninitializedPipeWrite
|
||||||
|
}
|
||||||
return p.b.Write(d)
|
return p.b.Write(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
vendor/golang.org/x/net/http2/server.go
generated
vendored
105
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -124,6 +124,7 @@ type Server struct {
|
|||||||
// IdleTimeout specifies how long until idle clients should be
|
// IdleTimeout specifies how long until idle clients should be
|
||||||
// closed with a GOAWAY frame. PING frames are not considered
|
// closed with a GOAWAY frame. PING frames are not considered
|
||||||
// activity for the purposes of IdleTimeout.
|
// activity for the purposes of IdleTimeout.
|
||||||
|
// If zero or negative, there is no timeout.
|
||||||
IdleTimeout time.Duration
|
IdleTimeout time.Duration
|
||||||
|
|
||||||
// MaxUploadBufferPerConnection is the size of the initial flow
|
// MaxUploadBufferPerConnection is the size of the initial flow
|
||||||
@ -434,7 +435,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
// passes the connection off to us with the deadline already set.
|
// passes the connection off to us with the deadline already set.
|
||||||
// Write deadlines are set per stream in serverConn.newStream.
|
// Write deadlines are set per stream in serverConn.newStream.
|
||||||
// Disarm the net.Conn write deadline here.
|
// Disarm the net.Conn write deadline here.
|
||||||
if sc.hs.WriteTimeout != 0 {
|
if sc.hs.WriteTimeout > 0 {
|
||||||
sc.conn.SetWriteDeadline(time.Time{})
|
sc.conn.SetWriteDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,9 +582,11 @@ type serverConn struct {
|
|||||||
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
|
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
|
||||||
curClientStreams uint32 // number of open streams initiated by the client
|
curClientStreams uint32 // number of open streams initiated by the client
|
||||||
curPushedStreams uint32 // number of open streams initiated by server push
|
curPushedStreams uint32 // number of open streams initiated by server push
|
||||||
|
curHandlers uint32 // number of running handler goroutines
|
||||||
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
|
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
|
||||||
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
||||||
streams map[uint32]*stream
|
streams map[uint32]*stream
|
||||||
|
unstartedHandlers []unstartedHandler
|
||||||
initialStreamSendWindowSize int32
|
initialStreamSendWindowSize int32
|
||||||
maxFrameSize int32
|
maxFrameSize int32
|
||||||
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
||||||
@ -922,7 +925,7 @@ func (sc *serverConn) serve() {
|
|||||||
sc.setConnState(http.StateActive)
|
sc.setConnState(http.StateActive)
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
|
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout > 0 {
|
||||||
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||||
defer sc.idleTimer.Stop()
|
defer sc.idleTimer.Stop()
|
||||||
}
|
}
|
||||||
@ -981,6 +984,8 @@ func (sc *serverConn) serve() {
|
|||||||
return
|
return
|
||||||
case gracefulShutdownMsg:
|
case gracefulShutdownMsg:
|
||||||
sc.startGracefulShutdownInternal()
|
sc.startGracefulShutdownInternal()
|
||||||
|
case handlerDoneMsg:
|
||||||
|
sc.handlerDone()
|
||||||
default:
|
default:
|
||||||
panic("unknown timer")
|
panic("unknown timer")
|
||||||
}
|
}
|
||||||
@ -1020,6 +1025,7 @@ var (
|
|||||||
idleTimerMsg = new(serverMessage)
|
idleTimerMsg = new(serverMessage)
|
||||||
shutdownTimerMsg = new(serverMessage)
|
shutdownTimerMsg = new(serverMessage)
|
||||||
gracefulShutdownMsg = new(serverMessage)
|
gracefulShutdownMsg = new(serverMessage)
|
||||||
|
handlerDoneMsg = new(serverMessage)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
||||||
@ -1632,7 +1638,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
delete(sc.streams, st.id)
|
delete(sc.streams, st.id)
|
||||||
if len(sc.streams) == 0 {
|
if len(sc.streams) == 0 {
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout > 0 {
|
||||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||||
}
|
}
|
||||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||||
@ -1892,10 +1898,12 @@ func (st *stream) copyTrailersToHandlerRequest() {
|
|||||||
// onReadTimeout is run on its own goroutine (from time.AfterFunc)
|
// onReadTimeout is run on its own goroutine (from time.AfterFunc)
|
||||||
// when the stream's ReadTimeout has fired.
|
// when the stream's ReadTimeout has fired.
|
||||||
func (st *stream) onReadTimeout() {
|
func (st *stream) onReadTimeout() {
|
||||||
|
if st.body != nil {
|
||||||
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
|
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
|
||||||
// returning the bare error.
|
// returning the bare error.
|
||||||
st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
|
st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
|
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
|
||||||
// when the stream's WriteTimeout has fired.
|
// when the stream's WriteTimeout has fired.
|
||||||
@ -2010,15 +2018,12 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
// similar to how the http1 server works. Here it's
|
// similar to how the http1 server works. Here it's
|
||||||
// technically more like the http1 Server's ReadHeaderTimeout
|
// technically more like the http1 Server's ReadHeaderTimeout
|
||||||
// (in Go 1.8), though. That's a more sane option anyway.
|
// (in Go 1.8), though. That's a more sane option anyway.
|
||||||
if sc.hs.ReadTimeout != 0 {
|
if sc.hs.ReadTimeout > 0 {
|
||||||
sc.conn.SetReadDeadline(time.Time{})
|
sc.conn.SetReadDeadline(time.Time{})
|
||||||
if st.body != nil {
|
|
||||||
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
go sc.runHandler(rw, req, handler)
|
return sc.scheduleHandler(id, rw, req, handler)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) upgradeRequest(req *http.Request) {
|
func (sc *serverConn) upgradeRequest(req *http.Request) {
|
||||||
@ -2034,10 +2039,14 @@ func (sc *serverConn) upgradeRequest(req *http.Request) {
|
|||||||
|
|
||||||
// Disable any read deadline set by the net/http package
|
// Disable any read deadline set by the net/http package
|
||||||
// prior to the upgrade.
|
// prior to the upgrade.
|
||||||
if sc.hs.ReadTimeout != 0 {
|
if sc.hs.ReadTimeout > 0 {
|
||||||
sc.conn.SetReadDeadline(time.Time{})
|
sc.conn.SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the first request on the connection,
|
||||||
|
// so start the handler directly rather than going
|
||||||
|
// through scheduleHandler.
|
||||||
|
sc.curHandlers++
|
||||||
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2108,7 +2117,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
|||||||
st.flow.conn = &sc.flow // link to conn-level counter
|
st.flow.conn = &sc.flow // link to conn-level counter
|
||||||
st.flow.add(sc.initialStreamSendWindowSize)
|
st.flow.add(sc.initialStreamSendWindowSize)
|
||||||
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
||||||
if sc.hs.WriteTimeout != 0 {
|
if sc.hs.WriteTimeout > 0 {
|
||||||
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2278,8 +2287,62 @@ func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *response
|
|||||||
return &responseWriter{rws: rws}
|
return &responseWriter{rws: rws}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type unstartedHandler struct {
|
||||||
|
streamID uint32
|
||||||
|
rw *responseWriter
|
||||||
|
req *http.Request
|
||||||
|
handler func(http.ResponseWriter, *http.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// scheduleHandler starts a handler goroutine,
|
||||||
|
// or schedules one to start as soon as an existing handler finishes.
|
||||||
|
func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error {
|
||||||
|
sc.serveG.check()
|
||||||
|
maxHandlers := sc.advMaxStreams
|
||||||
|
if sc.curHandlers < maxHandlers {
|
||||||
|
sc.curHandlers++
|
||||||
|
go sc.runHandler(rw, req, handler)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(sc.unstartedHandlers) > int(4*sc.advMaxStreams) {
|
||||||
|
return sc.countError("too_many_early_resets", ConnectionError(ErrCodeEnhanceYourCalm))
|
||||||
|
}
|
||||||
|
sc.unstartedHandlers = append(sc.unstartedHandlers, unstartedHandler{
|
||||||
|
streamID: streamID,
|
||||||
|
rw: rw,
|
||||||
|
req: req,
|
||||||
|
handler: handler,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc *serverConn) handlerDone() {
|
||||||
|
sc.serveG.check()
|
||||||
|
sc.curHandlers--
|
||||||
|
i := 0
|
||||||
|
maxHandlers := sc.advMaxStreams
|
||||||
|
for ; i < len(sc.unstartedHandlers); i++ {
|
||||||
|
u := sc.unstartedHandlers[i]
|
||||||
|
if sc.streams[u.streamID] == nil {
|
||||||
|
// This stream was reset before its goroutine had a chance to start.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if sc.curHandlers >= maxHandlers {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sc.curHandlers++
|
||||||
|
go sc.runHandler(u.rw, u.req, u.handler)
|
||||||
|
sc.unstartedHandlers[i] = unstartedHandler{} // don't retain references
|
||||||
|
}
|
||||||
|
sc.unstartedHandlers = sc.unstartedHandlers[i:]
|
||||||
|
if len(sc.unstartedHandlers) == 0 {
|
||||||
|
sc.unstartedHandlers = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Run on its own goroutine.
|
// Run on its own goroutine.
|
||||||
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
||||||
|
defer sc.sendServeMsg(handlerDoneMsg)
|
||||||
didPanic := true
|
didPanic := true
|
||||||
defer func() {
|
defer func() {
|
||||||
rw.rws.stream.cancelCtx()
|
rw.rws.stream.cancelCtx()
|
||||||
@ -2487,7 +2550,6 @@ type responseWriterState struct {
|
|||||||
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
||||||
sentHeader bool // have we sent the header frame?
|
sentHeader bool // have we sent the header frame?
|
||||||
handlerDone bool // handler has finished
|
handlerDone bool // handler has finished
|
||||||
dirty bool // a Write failed; don't reuse this responseWriterState
|
|
||||||
|
|
||||||
sentContentLen int64 // non-zero if handler set a Content-Length header
|
sentContentLen int64 // non-zero if handler set a Content-Length header
|
||||||
wroteBytes int64
|
wroteBytes int64
|
||||||
@ -2607,7 +2669,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
date: date,
|
date: date,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rws.dirty = true
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if endStream {
|
if endStream {
|
||||||
@ -2628,7 +2689,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
if len(p) > 0 || endStream {
|
if len(p) > 0 || endStream {
|
||||||
// only send a 0 byte DATA frame if we're ending the stream.
|
// only send a 0 byte DATA frame if we're ending the stream.
|
||||||
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
||||||
rws.dirty = true
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2640,9 +2700,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
trailers: rws.trailers,
|
trailers: rws.trailers,
|
||||||
endStream: true,
|
endStream: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
rws.dirty = true
|
|
||||||
}
|
|
||||||
return len(p), err
|
return len(p), err
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
@ -2858,14 +2915,12 @@ func (rws *responseWriterState) writeHeader(code int) {
|
|||||||
h.Del("Transfer-Encoding")
|
h.Del("Transfer-Encoding")
|
||||||
}
|
}
|
||||||
|
|
||||||
if rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
||||||
streamID: rws.stream.id,
|
streamID: rws.stream.id,
|
||||||
httpResCode: code,
|
httpResCode: code,
|
||||||
h: h,
|
h: h,
|
||||||
endStream: rws.handlerDone && !rws.hasTrailers(),
|
endStream: rws.handlerDone && !rws.hasTrailers(),
|
||||||
}) != nil {
|
})
|
||||||
rws.dirty = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2930,20 +2985,11 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
|
|||||||
|
|
||||||
func (w *responseWriter) handlerDone() {
|
func (w *responseWriter) handlerDone() {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
dirty := rws.dirty
|
|
||||||
rws.handlerDone = true
|
rws.handlerDone = true
|
||||||
w.Flush()
|
w.Flush()
|
||||||
w.rws = nil
|
w.rws = nil
|
||||||
if !dirty {
|
|
||||||
// Only recycle the pool if all prior Write calls to
|
|
||||||
// the serverConn goroutine completed successfully. If
|
|
||||||
// they returned earlier due to resets from the peer
|
|
||||||
// there might still be write goroutines outstanding
|
|
||||||
// from the serverConn referencing the rws memory. See
|
|
||||||
// issue 20704.
|
|
||||||
responseWriterStatePool.Put(rws)
|
responseWriterStatePool.Put(rws)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Push errors.
|
// Push errors.
|
||||||
var (
|
var (
|
||||||
@ -3125,6 +3171,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
|
|||||||
panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
|
panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc.curHandlers++
|
||||||
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
||||||
return promisedID, nil
|
return promisedID, nil
|
||||||
}
|
}
|
||||||
|
331
vendor/golang.org/x/net/http2/testsync.go
generated
vendored
Normal file
331
vendor/golang.org/x/net/http2/testsync.go
generated
vendored
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testSyncHooks coordinates goroutines in tests.
|
||||||
|
//
|
||||||
|
// For example, a call to ClientConn.RoundTrip involves several goroutines, including:
|
||||||
|
// - the goroutine running RoundTrip;
|
||||||
|
// - the clientStream.doRequest goroutine, which writes the request; and
|
||||||
|
// - the clientStream.readLoop goroutine, which reads the response.
|
||||||
|
//
|
||||||
|
// Using testSyncHooks, a test can start a RoundTrip and identify when all these goroutines
|
||||||
|
// are blocked waiting for some condition such as reading the Request.Body or waiting for
|
||||||
|
// flow control to become available.
|
||||||
|
//
|
||||||
|
// The testSyncHooks also manage timers and synthetic time in tests.
|
||||||
|
// This permits us to, for example, start a request and cause it to time out waiting for
|
||||||
|
// response headers without resorting to time.Sleep calls.
|
||||||
|
type testSyncHooks struct {
|
||||||
|
// active/inactive act as a mutex and condition variable.
|
||||||
|
//
|
||||||
|
// - neither chan contains a value: testSyncHooks is locked.
|
||||||
|
// - active contains a value: unlocked, and at least one goroutine is not blocked
|
||||||
|
// - inactive contains a value: unlocked, and all goroutines are blocked
|
||||||
|
active chan struct{}
|
||||||
|
inactive chan struct{}
|
||||||
|
|
||||||
|
// goroutine counts
|
||||||
|
total int // total goroutines
|
||||||
|
condwait map[*sync.Cond]int // blocked in sync.Cond.Wait
|
||||||
|
blocked []*testBlockedGoroutine // otherwise blocked
|
||||||
|
|
||||||
|
// fake time
|
||||||
|
now time.Time
|
||||||
|
timers []*fakeTimer
|
||||||
|
|
||||||
|
// Transport testing: Report various events.
|
||||||
|
newclientconn func(*ClientConn)
|
||||||
|
newstream func(*clientStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testBlockedGoroutine is a blocked goroutine.
|
||||||
|
type testBlockedGoroutine struct {
|
||||||
|
f func() bool // blocked until f returns true
|
||||||
|
ch chan struct{} // closed when unblocked
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestSyncHooks() *testSyncHooks {
|
||||||
|
h := &testSyncHooks{
|
||||||
|
active: make(chan struct{}, 1),
|
||||||
|
inactive: make(chan struct{}, 1),
|
||||||
|
condwait: map[*sync.Cond]int{},
|
||||||
|
}
|
||||||
|
h.inactive <- struct{}{}
|
||||||
|
h.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// lock acquires the testSyncHooks mutex.
|
||||||
|
func (h *testSyncHooks) lock() {
|
||||||
|
select {
|
||||||
|
case <-h.active:
|
||||||
|
case <-h.inactive:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitInactive waits for all goroutines to become inactive.
|
||||||
|
func (h *testSyncHooks) waitInactive() {
|
||||||
|
for {
|
||||||
|
<-h.inactive
|
||||||
|
if !h.unlock() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlock releases the testSyncHooks mutex.
|
||||||
|
// It reports whether any goroutines are active.
|
||||||
|
func (h *testSyncHooks) unlock() (active bool) {
|
||||||
|
// Look for a blocked goroutine which can be unblocked.
|
||||||
|
blocked := h.blocked[:0]
|
||||||
|
unblocked := false
|
||||||
|
for _, b := range h.blocked {
|
||||||
|
if !unblocked && b.f() {
|
||||||
|
unblocked = true
|
||||||
|
close(b.ch)
|
||||||
|
} else {
|
||||||
|
blocked = append(blocked, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.blocked = blocked
|
||||||
|
|
||||||
|
// Count goroutines blocked on condition variables.
|
||||||
|
condwait := 0
|
||||||
|
for _, count := range h.condwait {
|
||||||
|
condwait += count
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.total > condwait+len(blocked) {
|
||||||
|
h.active <- struct{}{}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
h.inactive <- struct{}{}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// goRun starts a new goroutine.
|
||||||
|
func (h *testSyncHooks) goRun(f func()) {
|
||||||
|
h.lock()
|
||||||
|
h.total++
|
||||||
|
h.unlock()
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
h.lock()
|
||||||
|
h.total--
|
||||||
|
h.unlock()
|
||||||
|
}()
|
||||||
|
f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// blockUntil indicates that a goroutine is blocked waiting for some condition to become true.
|
||||||
|
// It waits until f returns true before proceeding.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// h.blockUntil(func() bool {
|
||||||
|
// // Is the context done yet?
|
||||||
|
// select {
|
||||||
|
// case <-ctx.Done():
|
||||||
|
// default:
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
// // Wait for the context to become done.
|
||||||
|
// <-ctx.Done()
|
||||||
|
//
|
||||||
|
// The function f passed to blockUntil must be non-blocking and idempotent.
|
||||||
|
func (h *testSyncHooks) blockUntil(f func() bool) {
|
||||||
|
if f() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch := make(chan struct{})
|
||||||
|
h.lock()
|
||||||
|
h.blocked = append(h.blocked, &testBlockedGoroutine{
|
||||||
|
f: f,
|
||||||
|
ch: ch,
|
||||||
|
})
|
||||||
|
h.unlock()
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// broadcast is sync.Cond.Broadcast.
|
||||||
|
func (h *testSyncHooks) condBroadcast(cond *sync.Cond) {
|
||||||
|
h.lock()
|
||||||
|
delete(h.condwait, cond)
|
||||||
|
h.unlock()
|
||||||
|
cond.Broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
// broadcast is sync.Cond.Wait.
|
||||||
|
func (h *testSyncHooks) condWait(cond *sync.Cond) {
|
||||||
|
h.lock()
|
||||||
|
h.condwait[cond]++
|
||||||
|
h.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimer creates a new fake timer.
|
||||||
|
func (h *testSyncHooks) newTimer(d time.Duration) timer {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
t := &fakeTimer{
|
||||||
|
hooks: h,
|
||||||
|
when: h.now.Add(d),
|
||||||
|
c: make(chan time.Time),
|
||||||
|
}
|
||||||
|
h.timers = append(h.timers, t)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// afterFunc creates a new fake AfterFunc timer.
|
||||||
|
func (h *testSyncHooks) afterFunc(d time.Duration, f func()) timer {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
t := &fakeTimer{
|
||||||
|
hooks: h,
|
||||||
|
when: h.now.Add(d),
|
||||||
|
f: f,
|
||||||
|
}
|
||||||
|
h.timers = append(h.timers, t)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *testSyncHooks) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
t := h.afterFunc(d, cancel)
|
||||||
|
return ctx, func() {
|
||||||
|
t.Stop()
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *testSyncHooks) timeUntilEvent() time.Duration {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
var next time.Time
|
||||||
|
for _, t := range h.timers {
|
||||||
|
if next.IsZero() || t.when.Before(next) {
|
||||||
|
next = t.when
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d := next.Sub(h.now); d > 0 {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance advances time and causes synthetic timers to fire.
|
||||||
|
func (h *testSyncHooks) advance(d time.Duration) {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
h.now = h.now.Add(d)
|
||||||
|
timers := h.timers[:0]
|
||||||
|
for _, t := range h.timers {
|
||||||
|
t := t // remove after go.mod depends on go1.22
|
||||||
|
t.mu.Lock()
|
||||||
|
switch {
|
||||||
|
case t.when.After(h.now):
|
||||||
|
timers = append(timers, t)
|
||||||
|
case t.when.IsZero():
|
||||||
|
// stopped timer
|
||||||
|
default:
|
||||||
|
t.when = time.Time{}
|
||||||
|
if t.c != nil {
|
||||||
|
close(t.c)
|
||||||
|
}
|
||||||
|
if t.f != nil {
|
||||||
|
h.total++
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
h.lock()
|
||||||
|
h.total--
|
||||||
|
h.unlock()
|
||||||
|
}()
|
||||||
|
t.f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.mu.Unlock()
|
||||||
|
}
|
||||||
|
h.timers = timers
|
||||||
|
}
|
||||||
|
|
||||||
|
// A timer wraps a time.Timer, or a synthetic equivalent in tests.
|
||||||
|
// Unlike time.Timer, timer is single-use: The timer channel is closed when the timer expires.
|
||||||
|
type timer interface {
|
||||||
|
C() <-chan time.Time
|
||||||
|
Stop() bool
|
||||||
|
Reset(d time.Duration) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeTimer implements timer using real time.
|
||||||
|
type timeTimer struct {
|
||||||
|
t *time.Timer
|
||||||
|
c chan time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimeTimer creates a new timer using real time.
|
||||||
|
func newTimeTimer(d time.Duration) timer {
|
||||||
|
ch := make(chan time.Time)
|
||||||
|
t := time.AfterFunc(d, func() {
|
||||||
|
close(ch)
|
||||||
|
})
|
||||||
|
return &timeTimer{t, ch}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimeAfterFunc creates an AfterFunc timer using real time.
|
||||||
|
func newTimeAfterFunc(d time.Duration, f func()) timer {
|
||||||
|
return &timeTimer{
|
||||||
|
t: time.AfterFunc(d, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t timeTimer) C() <-chan time.Time { return t.c }
|
||||||
|
func (t timeTimer) Stop() bool { return t.t.Stop() }
|
||||||
|
func (t timeTimer) Reset(d time.Duration) bool { return t.t.Reset(d) }
|
||||||
|
|
||||||
|
// fakeTimer implements timer using fake time.
|
||||||
|
type fakeTimer struct {
|
||||||
|
hooks *testSyncHooks
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
when time.Time // when the timer will fire
|
||||||
|
c chan time.Time // closed when the timer fires; mutually exclusive with f
|
||||||
|
f func() // called when the timer fires; mutually exclusive with c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *fakeTimer) C() <-chan time.Time { return t.c }
|
||||||
|
|
||||||
|
func (t *fakeTimer) Stop() bool {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
stopped := t.when.IsZero()
|
||||||
|
t.when = time.Time{}
|
||||||
|
return stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *fakeTimer) Reset(d time.Duration) bool {
|
||||||
|
if t.c != nil || t.f == nil {
|
||||||
|
panic("fakeTimer only supports Reset on AfterFunc timers")
|
||||||
|
}
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
t.hooks.lock()
|
||||||
|
defer t.hooks.unlock()
|
||||||
|
active := !t.when.IsZero()
|
||||||
|
t.when = t.hooks.now.Add(d)
|
||||||
|
if !active {
|
||||||
|
t.hooks.timers = append(t.hooks.timers, t)
|
||||||
|
}
|
||||||
|
return active
|
||||||
|
}
|
338
vendor/golang.org/x/net/http2/transport.go
generated
vendored
338
vendor/golang.org/x/net/http2/transport.go
generated
vendored
@ -147,6 +147,12 @@ type Transport struct {
|
|||||||
// waiting for their turn.
|
// waiting for their turn.
|
||||||
StrictMaxConcurrentStreams bool
|
StrictMaxConcurrentStreams bool
|
||||||
|
|
||||||
|
// IdleConnTimeout is the maximum amount of time an idle
|
||||||
|
// (keep-alive) connection will remain idle before closing
|
||||||
|
// itself.
|
||||||
|
// Zero means no limit.
|
||||||
|
IdleConnTimeout time.Duration
|
||||||
|
|
||||||
// ReadIdleTimeout is the timeout after which a health check using ping
|
// ReadIdleTimeout is the timeout after which a health check using ping
|
||||||
// frame will be carried out if no frame is received on the connection.
|
// frame will be carried out if no frame is received on the connection.
|
||||||
// Note that a ping response will is considered a received frame, so if
|
// Note that a ping response will is considered a received frame, so if
|
||||||
@ -178,6 +184,8 @@ type Transport struct {
|
|||||||
|
|
||||||
connPoolOnce sync.Once
|
connPoolOnce sync.Once
|
||||||
connPoolOrDef ClientConnPool // non-nil version of ConnPool
|
connPoolOrDef ClientConnPool // non-nil version of ConnPool
|
||||||
|
|
||||||
|
syncHooks *testSyncHooks
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) maxHeaderListSize() uint32 {
|
func (t *Transport) maxHeaderListSize() uint32 {
|
||||||
@ -302,7 +310,7 @@ type ClientConn struct {
|
|||||||
readerErr error // set before readerDone is closed
|
readerErr error // set before readerDone is closed
|
||||||
|
|
||||||
idleTimeout time.Duration // or 0 for never
|
idleTimeout time.Duration // or 0 for never
|
||||||
idleTimer *time.Timer
|
idleTimer timer
|
||||||
|
|
||||||
mu sync.Mutex // guards following
|
mu sync.Mutex // guards following
|
||||||
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
||||||
@ -344,6 +352,60 @@ type ClientConn struct {
|
|||||||
werr error // first write error that has occurred
|
werr error // first write error that has occurred
|
||||||
hbuf bytes.Buffer // HPACK encoder writes into this
|
hbuf bytes.Buffer // HPACK encoder writes into this
|
||||||
henc *hpack.Encoder
|
henc *hpack.Encoder
|
||||||
|
|
||||||
|
syncHooks *testSyncHooks // can be nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook points used for testing.
|
||||||
|
// Outside of tests, cc.syncHooks is nil and these all have minimal implementations.
|
||||||
|
// Inside tests, see the testSyncHooks function docs.
|
||||||
|
|
||||||
|
// goRun starts a new goroutine.
|
||||||
|
func (cc *ClientConn) goRun(f func()) {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.goRun(f)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f()
|
||||||
|
}
|
||||||
|
|
||||||
|
// condBroadcast is cc.cond.Broadcast.
|
||||||
|
func (cc *ClientConn) condBroadcast() {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.condBroadcast(cc.cond)
|
||||||
|
}
|
||||||
|
cc.cond.Broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
// condWait is cc.cond.Wait.
|
||||||
|
func (cc *ClientConn) condWait() {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.condWait(cc.cond)
|
||||||
|
}
|
||||||
|
cc.cond.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimer creates a new time.Timer, or a synthetic timer in tests.
|
||||||
|
func (cc *ClientConn) newTimer(d time.Duration) timer {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.newTimer(d)
|
||||||
|
}
|
||||||
|
return newTimeTimer(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
|
||||||
|
func (cc *ClientConn) afterFunc(d time.Duration, f func()) timer {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.afterFunc(d, f)
|
||||||
|
}
|
||||||
|
return newTimeAfterFunc(d, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.contextWithTimeout(ctx, d)
|
||||||
|
}
|
||||||
|
return context.WithTimeout(ctx, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientStream is the state for a single HTTP/2 stream. One of these
|
// clientStream is the state for a single HTTP/2 stream. One of these
|
||||||
@ -425,7 +487,7 @@ func (cs *clientStream) abortStreamLocked(err error) {
|
|||||||
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
||||||
if cs.cc.cond != nil {
|
if cs.cc.cond != nil {
|
||||||
// Wake up writeRequestBody if it is waiting on flow control.
|
// Wake up writeRequestBody if it is waiting on flow control.
|
||||||
cs.cc.cond.Broadcast()
|
cs.cc.condBroadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +497,7 @@ func (cs *clientStream) abortRequestBodyWrite() {
|
|||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
cs.closeReqBodyLocked()
|
cs.closeReqBodyLocked()
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,10 +507,10 @@ func (cs *clientStream) closeReqBodyLocked() {
|
|||||||
}
|
}
|
||||||
cs.reqBodyClosed = make(chan struct{})
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
reqBodyClosed := cs.reqBodyClosed
|
reqBodyClosed := cs.reqBodyClosed
|
||||||
go func() {
|
cs.cc.goRun(func() {
|
||||||
cs.reqBody.Close()
|
cs.reqBody.Close()
|
||||||
close(reqBodyClosed)
|
close(reqBodyClosed)
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type stickyErrWriter struct {
|
type stickyErrWriter struct {
|
||||||
@ -537,15 +599,6 @@ func authorityAddr(scheme string, authority string) (addr string) {
|
|||||||
return net.JoinHostPort(host, port)
|
return net.JoinHostPort(host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
var retryBackoffHook func(time.Duration) *time.Timer
|
|
||||||
|
|
||||||
func backoffNewTimer(d time.Duration) *time.Timer {
|
|
||||||
if retryBackoffHook != nil {
|
|
||||||
return retryBackoffHook(d)
|
|
||||||
}
|
|
||||||
return time.NewTimer(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundTripOpt is like RoundTrip, but takes options.
|
// RoundTripOpt is like RoundTrip, but takes options.
|
||||||
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
||||||
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
|
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
|
||||||
@ -573,13 +626,27 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
|||||||
backoff := float64(uint(1) << (uint(retry) - 1))
|
backoff := float64(uint(1) << (uint(retry) - 1))
|
||||||
backoff += backoff * (0.1 * mathrand.Float64())
|
backoff += backoff * (0.1 * mathrand.Float64())
|
||||||
d := time.Second * time.Duration(backoff)
|
d := time.Second * time.Duration(backoff)
|
||||||
timer := backoffNewTimer(d)
|
var tm timer
|
||||||
|
if t.syncHooks != nil {
|
||||||
|
tm = t.syncHooks.newTimer(d)
|
||||||
|
t.syncHooks.blockUntil(func() bool {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-tm.C():
|
||||||
|
case <-req.Context().Done():
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tm = newTimeTimer(d)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-tm.C():
|
||||||
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
||||||
continue
|
continue
|
||||||
case <-req.Context().Done():
|
case <-req.Context().Done():
|
||||||
timer.Stop()
|
tm.Stop()
|
||||||
err = req.Context().Err()
|
err = req.Context().Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -658,6 +725,9 @@ func canRetryError(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
|
||||||
|
if t.syncHooks != nil {
|
||||||
|
return t.newClientConn(nil, singleUse, t.syncHooks)
|
||||||
|
}
|
||||||
host, _, err := net.SplitHostPort(addr)
|
host, _, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -666,7 +736,7 @@ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return t.newClientConn(tconn, singleUse)
|
return t.newClientConn(tconn, singleUse, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) newTLSConfig(host string) *tls.Config {
|
func (t *Transport) newTLSConfig(host string) *tls.Config {
|
||||||
@ -732,10 +802,10 @@ func (t *Transport) maxEncoderHeaderTableSize() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
|
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
|
||||||
return t.newClientConn(c, t.disableKeepAlives())
|
return t.newClientConn(c, t.disableKeepAlives(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHooks) (*ClientConn, error) {
|
||||||
cc := &ClientConn{
|
cc := &ClientConn{
|
||||||
t: t,
|
t: t,
|
||||||
tconn: c,
|
tconn: c,
|
||||||
@ -750,10 +820,15 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
wantSettingsAck: true,
|
wantSettingsAck: true,
|
||||||
pings: make(map[[8]byte]chan struct{}),
|
pings: make(map[[8]byte]chan struct{}),
|
||||||
reqHeaderMu: make(chan struct{}, 1),
|
reqHeaderMu: make(chan struct{}, 1),
|
||||||
|
syncHooks: hooks,
|
||||||
|
}
|
||||||
|
if hooks != nil {
|
||||||
|
hooks.newclientconn(cc)
|
||||||
|
c = cc.tconn
|
||||||
}
|
}
|
||||||
if d := t.idleConnTimeout(); d != 0 {
|
if d := t.idleConnTimeout(); d != 0 {
|
||||||
cc.idleTimeout = d
|
cc.idleTimeout = d
|
||||||
cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
|
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
|
||||||
}
|
}
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
|
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
|
||||||
@ -818,7 +893,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
return nil, cc.werr
|
return nil, cc.werr
|
||||||
}
|
}
|
||||||
|
|
||||||
go cc.readLoop()
|
cc.goRun(cc.readLoop)
|
||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,7 +901,7 @@ func (cc *ClientConn) healthCheck() {
|
|||||||
pingTimeout := cc.t.pingTimeout()
|
pingTimeout := cc.t.pingTimeout()
|
||||||
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
|
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
|
||||||
// trigger the healthCheck again if there is no frame received.
|
// trigger the healthCheck again if there is no frame received.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
|
ctx, cancel := cc.contextWithTimeout(context.Background(), pingTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cc.vlogf("http2: Transport sending health check")
|
cc.vlogf("http2: Transport sending health check")
|
||||||
err := cc.Ping(ctx)
|
err := cc.Ping(ctx)
|
||||||
@ -1018,7 +1093,7 @@ func (cc *ClientConn) forceCloseConn() {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if nc := tlsUnderlyingConn(tc); nc != nil {
|
if nc := tc.NetConn(); nc != nil {
|
||||||
nc.Close()
|
nc.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1056,7 +1131,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
// Wait for all in-flight streams to complete or connection to close
|
// Wait for all in-flight streams to complete or connection to close
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
cancelled := false // guarded by cc.mu
|
cancelled := false // guarded by cc.mu
|
||||||
go func() {
|
cc.goRun(func() {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
for {
|
for {
|
||||||
@ -1068,9 +1143,9 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
if cancelled {
|
if cancelled {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
shutdownEnterWaitStateHook()
|
shutdownEnterWaitStateHook()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
@ -1080,7 +1155,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
// Free the goroutine above
|
// Free the goroutine above
|
||||||
cancelled = true
|
cancelled = true
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
@ -1118,7 +1193,7 @@ func (cc *ClientConn) closeForError(err error) {
|
|||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
cs.abortStreamLocked(err)
|
cs.abortStreamLocked(err)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
cc.closeConn()
|
cc.closeConn()
|
||||||
}
|
}
|
||||||
@ -1215,6 +1290,10 @@ func (cc *ClientConn) decrStreamReservationsLocked() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
return cc.roundTrip(req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) (*http.Response, error) {
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
cs := &clientStream{
|
cs := &clientStream{
|
||||||
cc: cc,
|
cc: cc,
|
||||||
@ -1229,9 +1308,23 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
respHeaderRecv: make(chan struct{}),
|
respHeaderRecv: make(chan struct{}),
|
||||||
donec: make(chan struct{}),
|
donec: make(chan struct{}),
|
||||||
}
|
}
|
||||||
go cs.doRequest(req)
|
cc.goRun(func() {
|
||||||
|
cs.doRequest(req)
|
||||||
|
})
|
||||||
|
|
||||||
waitDone := func() error {
|
waitDone := func() error {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.donec:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.donec:
|
case <-cs.donec:
|
||||||
return nil
|
return nil
|
||||||
@ -1292,7 +1385,24 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamf != nil {
|
||||||
|
streamf(cs)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.respHeaderRecv:
|
||||||
|
case <-cs.abort:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.respHeaderRecv:
|
case <-cs.respHeaderRecv:
|
||||||
return handleResponseHeaders()
|
return handleResponseHeaders()
|
||||||
@ -1348,6 +1458,21 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
if cc.reqHeaderMu == nil {
|
if cc.reqHeaderMu == nil {
|
||||||
panic("RoundTrip on uninitialized ClientConn") // for tests
|
panic("RoundTrip on uninitialized ClientConn") // for tests
|
||||||
}
|
}
|
||||||
|
var newStreamHook func(*clientStream)
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
newStreamHook = cc.syncHooks.newstream
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case cc.reqHeaderMu <- struct{}{}:
|
||||||
|
<-cc.reqHeaderMu
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
case <-ctx.Done():
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case cc.reqHeaderMu <- struct{}{}:
|
case cc.reqHeaderMu <- struct{}{}:
|
||||||
case <-cs.reqCancel:
|
case <-cs.reqCancel:
|
||||||
@ -1372,6 +1497,10 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
|
if newStreamHook != nil {
|
||||||
|
newStreamHook(cs)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
||||||
if !cc.t.disableCompression() &&
|
if !cc.t.disableCompression() &&
|
||||||
req.Header.Get("Accept-Encoding") == "" &&
|
req.Header.Get("Accept-Encoding") == "" &&
|
||||||
@ -1452,15 +1581,30 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
var respHeaderTimer <-chan time.Time
|
var respHeaderTimer <-chan time.Time
|
||||||
var respHeaderRecv chan struct{}
|
var respHeaderRecv chan struct{}
|
||||||
if d := cc.responseHeaderTimeout(); d != 0 {
|
if d := cc.responseHeaderTimeout(); d != 0 {
|
||||||
timer := time.NewTimer(d)
|
timer := cc.newTimer(d)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
respHeaderTimer = timer.C
|
respHeaderTimer = timer.C()
|
||||||
respHeaderRecv = cs.respHeaderRecv
|
respHeaderRecv = cs.respHeaderRecv
|
||||||
}
|
}
|
||||||
// Wait until the peer half-closes its end of the stream,
|
// Wait until the peer half-closes its end of the stream,
|
||||||
// or until the request is aborted (via context, error, or otherwise),
|
// or until the request is aborted (via context, error, or otherwise),
|
||||||
// whichever comes first.
|
// whichever comes first.
|
||||||
for {
|
for {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.peerClosed:
|
||||||
|
case <-respHeaderTimer:
|
||||||
|
case <-respHeaderRecv:
|
||||||
|
case <-cs.abort:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.peerClosed:
|
case <-cs.peerClosed:
|
||||||
return nil
|
return nil
|
||||||
@ -1609,7 +1753,7 @@ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cc.pendingRequests++
|
cc.pendingRequests++
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
cc.pendingRequests--
|
cc.pendingRequests--
|
||||||
select {
|
select {
|
||||||
case <-cs.abort:
|
case <-cs.abort:
|
||||||
@ -1871,10 +2015,26 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
|
|||||||
cs.flow.take(take)
|
cs.flow.take(take)
|
||||||
return take, nil
|
return take, nil
|
||||||
}
|
}
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateHeaders(hdrs http.Header) string {
|
||||||
|
for k, vv := range hdrs {
|
||||||
|
if !httpguts.ValidHeaderFieldName(k) {
|
||||||
|
return fmt.Sprintf("name %q", k)
|
||||||
|
}
|
||||||
|
for _, v := range vv {
|
||||||
|
if !httpguts.ValidHeaderFieldValue(v) {
|
||||||
|
// Don't include the value in the error,
|
||||||
|
// because it may be sensitive.
|
||||||
|
return fmt.Sprintf("value for header %q", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var errNilRequestURL = errors.New("http2: Request.URI is nil")
|
var errNilRequestURL = errors.New("http2: Request.URI is nil")
|
||||||
|
|
||||||
// requires cc.wmu be held.
|
// requires cc.wmu be held.
|
||||||
@ -1912,19 +2072,14 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for any invalid headers and return an error before we
|
// Check for any invalid headers+trailers and return an error before we
|
||||||
// potentially pollute our hpack state. (We want to be able to
|
// potentially pollute our hpack state. (We want to be able to
|
||||||
// continue to reuse the hpack encoder for future requests)
|
// continue to reuse the hpack encoder for future requests)
|
||||||
for k, vv := range req.Header {
|
if err := validateHeaders(req.Header); err != "" {
|
||||||
if !httpguts.ValidHeaderFieldName(k) {
|
return nil, fmt.Errorf("invalid HTTP header %s", err)
|
||||||
return nil, fmt.Errorf("invalid HTTP header name %q", k)
|
|
||||||
}
|
|
||||||
for _, v := range vv {
|
|
||||||
if !httpguts.ValidHeaderFieldValue(v) {
|
|
||||||
// Don't include the value in the error, because it may be sensitive.
|
|
||||||
return nil, fmt.Errorf("invalid HTTP header value for header %q", k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if err := validateHeaders(req.Trailer); err != "" {
|
||||||
|
return nil, fmt.Errorf("invalid HTTP trailer %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerateHeaders := func(f func(name, value string)) {
|
enumerateHeaders := func(f func(name, value string)) {
|
||||||
@ -2143,7 +2298,7 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
|
|||||||
}
|
}
|
||||||
// Wake up writeRequestBody via clientStream.awaitFlowControl and
|
// Wake up writeRequestBody via clientStream.awaitFlowControl and
|
||||||
// wake up RoundTrip if there is a pending request.
|
// wake up RoundTrip if there is a pending request.
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
|
|
||||||
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
|
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
|
||||||
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
||||||
@ -2231,7 +2386,7 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||||||
cs.abortStreamLocked(err)
|
cs.abortStreamLocked(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2266,10 +2421,9 @@ func (rl *clientConnReadLoop) run() error {
|
|||||||
cc := rl.cc
|
cc := rl.cc
|
||||||
gotSettings := false
|
gotSettings := false
|
||||||
readIdleTimeout := cc.t.ReadIdleTimeout
|
readIdleTimeout := cc.t.ReadIdleTimeout
|
||||||
var t *time.Timer
|
var t timer
|
||||||
if readIdleTimeout != 0 {
|
if readIdleTimeout != 0 {
|
||||||
t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
|
t = cc.afterFunc(readIdleTimeout, cc.healthCheck)
|
||||||
defer t.Stop()
|
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
f, err := cc.fr.ReadFrame()
|
f, err := cc.fr.ReadFrame()
|
||||||
@ -2684,7 +2838,7 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !cs.firstByte {
|
if !cs.pastHeaders {
|
||||||
cc.logf("protocol error: received DATA before a HEADERS frame")
|
cc.logf("protocol error: received DATA before a HEADERS frame")
|
||||||
rl.endStreamError(cs, StreamError{
|
rl.endStreamError(cs, StreamError{
|
||||||
StreamID: f.StreamID,
|
StreamID: f.StreamID,
|
||||||
@ -2867,7 +3021,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
|||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
cs.flow.add(delta)
|
cs.flow.add(delta)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
|
|
||||||
cc.initialWindowSize = s.Val
|
cc.initialWindowSize = s.Val
|
||||||
case SettingHeaderTableSize:
|
case SettingHeaderTableSize:
|
||||||
@ -2911,9 +3065,18 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
|
|||||||
fl = &cs.flow
|
fl = &cs.flow
|
||||||
}
|
}
|
||||||
if !fl.add(int32(f.Increment)) {
|
if !fl.add(int32(f.Increment)) {
|
||||||
|
// For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
|
||||||
|
if cs != nil {
|
||||||
|
rl.endStreamError(cs, StreamError{
|
||||||
|
StreamID: f.StreamID,
|
||||||
|
Code: ErrCodeFlowControl,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return ConnectionError(ErrCodeFlowControl)
|
return ConnectionError(ErrCodeFlowControl)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2955,24 +3118,38 @@ func (cc *ClientConn) Ping(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
}
|
}
|
||||||
errc := make(chan error, 1)
|
var pingError error
|
||||||
go func() {
|
errc := make(chan struct{})
|
||||||
|
cc.goRun(func() {
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
defer cc.wmu.Unlock()
|
defer cc.wmu.Unlock()
|
||||||
if err := cc.fr.WritePing(false, p); err != nil {
|
if pingError = cc.fr.WritePing(false, p); pingError != nil {
|
||||||
errc <- err
|
close(errc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := cc.bw.Flush(); err != nil {
|
if pingError = cc.bw.Flush(); pingError != nil {
|
||||||
errc <- err
|
close(errc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
case <-errc:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cc.readerDone:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-c:
|
case <-c:
|
||||||
return nil
|
return nil
|
||||||
case err := <-errc:
|
case <-errc:
|
||||||
return err
|
return pingError
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-cc.readerDone:
|
case <-cc.readerDone:
|
||||||
@ -3141,9 +3318,17 @@ func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) idleConnTimeout() time.Duration {
|
func (t *Transport) idleConnTimeout() time.Duration {
|
||||||
|
// to keep things backwards compatible, we use non-zero values of
|
||||||
|
// IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
|
||||||
|
// http1 transport, followed by 0
|
||||||
|
if t.IdleConnTimeout != 0 {
|
||||||
|
return t.IdleConnTimeout
|
||||||
|
}
|
||||||
|
|
||||||
if t.t1 != nil {
|
if t.t1 != nil {
|
||||||
return t.t1.IdleConnTimeout
|
return t.t1.IdleConnTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3201,3 +3386,34 @@ func traceFirstResponseByte(trace *httptrace.ClientTrace) {
|
|||||||
trace.GotFirstResponseByte()
|
trace.GotFirstResponseByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
||||||
|
return trace != nil && trace.WroteHeaderField != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
||||||
|
if trace != nil && trace.WroteHeaderField != nil {
|
||||||
|
trace.WroteHeaderField(k, []string{v})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
if trace != nil {
|
||||||
|
return trace.Got1xxResponse
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
|
||||||
|
// connection.
|
||||||
|
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
||||||
|
dialer := &tls.Dialer{
|
||||||
|
Config: cfg,
|
||||||
|
}
|
||||||
|
cn, err := dialer.DialContext(ctx, network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
|
||||||
|
return tlsCn, nil
|
||||||
|
}
|
||||||
|
1
vendor/golang.org/x/net/idna/go118.go
generated
vendored
1
vendor/golang.org/x/net/idna/go118.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.18
|
//go:build go1.18
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/idna10.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/idna10.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.10
|
//go:build go1.10
|
||||||
// +build go1.10
|
|
||||||
|
|
||||||
// Package idna implements IDNA2008 using the compatibility processing
|
// Package idna implements IDNA2008 using the compatibility processing
|
||||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||||
|
1
vendor/golang.org/x/net/idna/idna9.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/idna9.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.10
|
//go:build !go1.10
|
||||||
// +build !go1.10
|
|
||||||
|
|
||||||
// Package idna implements IDNA2008 using the compatibility processing
|
// Package idna implements IDNA2008 using the compatibility processing
|
||||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||||
|
1
vendor/golang.org/x/net/idna/pre_go118.go
generated
vendored
1
vendor/golang.org/x/net/idna/pre_go118.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.18
|
//go:build !go1.18
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables10.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables10.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.10 && !go1.13
|
//go:build go1.10 && !go1.13
|
||||||
// +build go1.10,!go1.13
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables11.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables11.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.13 && !go1.14
|
//go:build go1.13 && !go1.14
|
||||||
// +build go1.13,!go1.14
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables12.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables12.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.14 && !go1.16
|
//go:build go1.14 && !go1.16
|
||||||
// +build go1.14,!go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.16 && !go1.21
|
//go:build go1.16 && !go1.21
|
||||||
// +build go1.16,!go1.21
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables15.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables15.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.21
|
//go:build go1.21
|
||||||
// +build go1.21
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables9.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables9.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build !go1.10
|
//go:build !go1.10
|
||||||
// +build !go1.10
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/trie12.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/trie12.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.16
|
//go:build !go1.16
|
||||||
// +build !go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/trie13.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/trie13.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.16
|
//go:build go1.16
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// Copyright 2020 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package unsafeheader contains header declarations for the Go runtime's
|
|
||||||
// slice and string implementations.
|
|
||||||
//
|
|
||||||
// This package allows x/sys to use types equivalent to
|
|
||||||
// reflect.SliceHeader and reflect.StringHeader without introducing
|
|
||||||
// a dependency on the (relatively heavy) "reflect" package.
|
|
||||||
package unsafeheader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Slice is the runtime representation of a slice.
|
|
||||||
// It cannot be used safely or portably and its representation may change in a later release.
|
|
||||||
type Slice struct {
|
|
||||||
Data unsafe.Pointer
|
|
||||||
Len int
|
|
||||||
Cap int
|
|
||||||
}
|
|
||||||
|
|
||||||
// String is the runtime representation of a string.
|
|
||||||
// It cannot be used safely or portably and its representation may change in a later release.
|
|
||||||
type String struct {
|
|
||||||
Data unsafe.Pointer
|
|
||||||
Len int
|
|
||||||
}
|
|
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
@ -2,9 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
// +build go1.9
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
// +build freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||||
// +build darwin dragonfly freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
// +build freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user