Bump github.com/nickname76/telegrambot from 1.2.1 to 1.2.2 (#129)

Bumps [github.com/nickname76/telegrambot](https://github.com/nickname76/telegrambot) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/nickname76/telegrambot/releases)
- [Commits](https://github.com/nickname76/telegrambot/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: github.com/nickname76/telegrambot
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot] 2022-09-13 11:52:38 -07:00 committed by GitHub
parent c7fb0335a0
commit 9ddec2fd71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 420 additions and 553 deletions

4
go.mod
View File

@ -20,7 +20,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4
github.com/jackc/pgconn v1.13.0
github.com/jackc/pgx/v4 v4.17.2
github.com/nickname76/telegrambot v1.2.1
github.com/nickname76/telegrambot v1.2.2
github.com/nicksnyder/go-i18n/v2 v2.2.0
github.com/rbcervilla/redisstore/v8 v8.1.0
github.com/sirupsen/logrus v1.9.0
@ -96,7 +96,7 @@ require (
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
github.com/uptrace/opentelemetry-go-extra/otelsql v0.1.15 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.38.0 // indirect
github.com/valyala/fasthttp v1.40.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opentelemetry.io/contrib/instrumentation/runtime v0.34.0 // indirect

8
go.sum
View File

@ -360,8 +360,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nickname76/repeater v1.0.1 h1:RLACAbPHMwn37XvwwwTtqhZMa/M1nwsodxQ5rmjzh/s=
github.com/nickname76/repeater v1.0.1/go.mod h1:oJnqHAjbEamcjVBm8sHaexIVFdicS2YU6cJK0KZhgig=
github.com/nickname76/telegrambot v1.2.1 h1:9JaeUVkkJ9/C9WJ93pGbeOV5zsPQ8XIO8coJQ80FxM0=
github.com/nickname76/telegrambot v1.2.1/go.mod h1:0m8zn4r0Hb1+GmBEj9SoxQBhG1tg+pBEaKZ9agMeFDQ=
github.com/nickname76/telegrambot v1.2.2 h1:rEWpKyw0iwUAd0DyXyf88ZwxumMbpovkB7ddkfxXlC4=
github.com/nickname76/telegrambot v1.2.2/go.mod h1:UmHYek5rXXBzH3zJLy1LwvZFvKeWQSeGlDsz01l4Y94=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -474,8 +474,8 @@ github.com/uptrace/uptrace-go v1.9.0/go.mod h1:EJpFb3syIxnGa6cuvIxAMGzySSNn+CFOI
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.38.0 h1:yTjSSNjuDi2PPvXY2836bIwLmiTS2T4T9p1coQshpco=
github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc=
github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=

View File

@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://t.me/nickname76.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@ -1 +0,0 @@
Please be free to contribute every change that is needed for YOU. It can be small, or large, or just cosmetical. Everything gets reviewed and nothing gets rejected without discussion.

View File

@ -1,21 +1,25 @@
# Telegrambot
# [<img src="https://user-images.githubusercontent.com/41116859/185259360-b9b44eb2-6e47-4451-8d1e-90e3e4f34eef.png" height="32" /> Telegrambot](https://github.com/nickname76/telegrambot#example-usage) [<img class="badge" tag="github.com/nickname76/telegrambot" align="right" src="https://goreportcard.com/badge/github.com/nickname76/telegrambot">](https://goreportcard.com/report/github.com/nickname76/telegrambot)
Telegram Bot API library in Go. The easest to use, the most clean, and strongly typed Telegram Bot API library in Go.
[<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fstatic.wixstatic.com%2Fmedia%2F950c70_eb49b9b040b14b70972c9777d736f7ea~mv2_d_2112_2112_s_2.gif&f=1&nofb=1" align="right" height="240" />](https://discord.gg/rX4EhxsW6X)
Completely covers latest Bot API version - **6.2**.
The most clean and strongly typed Telegram Bot API library in Go
Completely covers the latest Bot API version - **6.2**
Telegram Bot API documentaion: https://core.telegram.org/bots/api
Also check out Telegram deep links: https://t.me/DeepLink
Telegram deep links list: https://corefork.telegram.org/api/links
Documentation on this library: https://pkg.go.dev/github.com/nickname76/telegrambot
Documentation on `/tools` directory: https://pkg.go.dev/github.com/nickname76/telegrambot/tools
*Please, **star** this repository, if you found this library useful.*
More Telegram deep links: https://t.me/DeepLink
**DISCORD**: [https://discord.gg/golang](https://discord.gg/rX4EhxsW6X) (#telegrambot channel)
**Documentation on this library:**
- API https://pkg.go.dev/github.com/nickname76/telegrambot
- Tools https://pkg.go.dev/github.com/nickname76/telegrambot/tools
*Please, **star** this repository, if you found this library useful!*
## Example usage
```Go

View File

@ -92,10 +92,10 @@ var (
//
// Supported compression levels are:
//
// * CompressBrotliNoCompression
// * CompressBrotliBestSpeed
// * CompressBrotliBestCompression
// * CompressBrotliDefaultCompression
// - CompressBrotliNoCompression
// - CompressBrotliBestSpeed
// - CompressBrotliBestCompression
// - CompressBrotliDefaultCompression
func AppendBrotliBytesLevel(dst, src []byte, level int) []byte {
w := &byteSliceWriter{dst}
WriteBrotliLevel(w, src, level) //nolint:errcheck
@ -107,10 +107,10 @@ func AppendBrotliBytesLevel(dst, src []byte, level int) []byte {
//
// Supported compression levels are:
//
// * CompressBrotliNoCompression
// * CompressBrotliBestSpeed
// * CompressBrotliBestCompression
// * CompressBrotliDefaultCompression
// - CompressBrotliNoCompression
// - CompressBrotliBestSpeed
// - CompressBrotliBestCompression
// - CompressBrotliDefaultCompression
func WriteBrotliLevel(w io.Writer, p []byte, level int) (int, error) {
switch w.(type) {
case *byteSliceWriter,

View File

@ -252,9 +252,7 @@ var (
)
func readHexInt(r *bufio.Reader) (int, error) {
n := 0
i := 0
var k int
var k, i, n int
for {
c, err := r.ReadByte()
if err != nil {

View File

@ -387,7 +387,8 @@ func (c *Client) Post(dst []byte, url string, postArgs *Args) (statusCode int, b
// If requests take too long and the connection pool gets filled up please
// try setting a ReadTimeout.
func (c *Client) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
return clientDoTimeout(req, resp, timeout, c)
req.timeout = timeout
return c.Do(req, resp)
}
// DoDeadline performs the given request and waits for response until
@ -414,7 +415,8 @@ func (c *Client) DoTimeout(req *Request, resp *Response, timeout time.Duration)
// It is recommended obtaining req and resp via AcquireRequest
// and AcquireResponse in performance-critical code.
func (c *Client) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
return clientDoDeadline(req, resp, deadline, c)
req.timeout = time.Until(deadline)
return c.Do(req, resp)
}
// DoRedirects performs the given http request and fills the given http response,
@ -1150,7 +1152,8 @@ func ReleaseResponse(resp *Response) {
// If requests take too long and the connection pool gets filled up please
// try setting a ReadTimeout.
func (c *HostClient) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
return clientDoTimeout(req, resp, timeout, c)
req.timeout = timeout
return c.Do(req, resp)
}
// DoDeadline performs the given request and waits for response until
@ -1172,7 +1175,8 @@ func (c *HostClient) DoTimeout(req *Request, resp *Response, timeout time.Durati
// It is recommended obtaining req and resp via AcquireRequest
// and AcquireResponse in performance-critical code.
func (c *HostClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
return clientDoDeadline(req, resp, deadline, c)
req.timeout = time.Until(deadline)
return c.Do(req, resp)
}
// DoRedirects performs the given http request and fills the given http response,
@ -1199,93 +1203,6 @@ func (c *HostClient) DoRedirects(req *Request, resp *Response, maxRedirectsCount
return err
}
func clientDoTimeout(req *Request, resp *Response, timeout time.Duration, c clientDoer) error {
deadline := time.Now().Add(timeout)
return clientDoDeadline(req, resp, deadline, c)
}
func clientDoDeadline(req *Request, resp *Response, deadline time.Time, c clientDoer) error {
timeout := -time.Since(deadline)
if timeout <= 0 {
return ErrTimeout
}
var ch chan error
chv := errorChPool.Get()
if chv == nil {
chv = make(chan error, 1)
}
ch = chv.(chan error)
// Make req and resp copies, since on timeout they no longer
// may be accessed.
reqCopy := AcquireRequest()
req.copyToSkipBody(reqCopy)
swapRequestBody(req, reqCopy)
respCopy := AcquireResponse()
if resp != nil {
// Not calling resp.copyToSkipBody(respCopy) here to avoid
// unexpected messing with headers
respCopy.SkipBody = resp.SkipBody
}
// Note that the request continues execution on ErrTimeout until
// client-specific ReadTimeout exceeds. This helps limiting load
// on slow hosts by MaxConns* concurrent requests.
//
// Without this 'hack' the load on slow host could exceed MaxConns*
// concurrent requests, since timed out requests on client side
// usually continue execution on the host.
var mu sync.Mutex
var timedout, responded bool
go func() {
reqCopy.timeout = timeout
errDo := c.Do(reqCopy, respCopy)
mu.Lock()
{
if !timedout {
if resp != nil {
respCopy.copyToSkipBody(resp)
swapResponseBody(resp, respCopy)
}
swapRequestBody(reqCopy, req)
ch <- errDo
responded = true
}
}
mu.Unlock()
ReleaseResponse(respCopy)
ReleaseRequest(reqCopy)
}()
tc := AcquireTimer(timeout)
var err error
select {
case err = <-ch:
case <-tc.C:
mu.Lock()
{
if responded {
err = <-ch
} else {
timedout = true
err = ErrTimeout
}
}
mu.Unlock()
}
ReleaseTimer(tc)
errorChPool.Put(chv)
return err
}
var errorChPool sync.Pool
// Do performs the given http request and sets the corresponding response.
//
// Request must contain at least non-zero RequestURI with full url (including
@ -1418,6 +1335,11 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error)
return err == nil, err
}
var deadline time.Time
if req.timeout > 0 {
deadline = time.Now().Add(req.timeout)
}
cc, err := c.acquireConn(req.timeout, req.ConnectionClose())
if err != nil {
return false, err
@ -1426,11 +1348,17 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error)
resp.parseNetConn(conn)
writeDeadline := deadline
if c.WriteTimeout > 0 {
tmpWriteDeadline := time.Now().Add(c.WriteTimeout)
if writeDeadline.IsZero() || tmpWriteDeadline.Before(writeDeadline) {
writeDeadline = tmpWriteDeadline
}
}
if !writeDeadline.IsZero() {
// Set Deadline every time, since golang has fixed the performance issue
// See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details
currentTime := time.Now()
if err = conn.SetWriteDeadline(currentTime.Add(c.WriteTimeout)); err != nil {
if err = conn.SetWriteDeadline(writeDeadline); err != nil {
c.closeConn(cc)
return true, err
}
@ -1453,17 +1381,29 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error)
err = bw.Flush()
}
c.releaseWriter(bw)
// Return ErrTimeout on any timeout.
if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
err = ErrTimeout
}
isConnRST := isConnectionReset(err)
if err != nil && !isConnRST {
c.closeConn(cc)
return true, err
}
readDeadline := deadline
if c.ReadTimeout > 0 {
tmpReadDeadline := time.Now().Add(c.ReadTimeout)
if readDeadline.IsZero() || tmpReadDeadline.Before(readDeadline) {
readDeadline = tmpReadDeadline
}
}
if !readDeadline.IsZero() {
// Set Deadline every time, since golang has fixed the performance issue
// See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details
currentTime := time.Now()
if err = conn.SetReadDeadline(currentTime.Add(c.ReadTimeout)); err != nil {
if err = conn.SetReadDeadline(readDeadline); err != nil {
c.closeConn(cc)
return true, err
}
@ -1527,7 +1467,7 @@ func (e *timeoutError) Error() string {
// Only implement the Timeout() function of the net.Error interface.
// This allows for checks like:
//
// if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
// if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
func (e *timeoutError) Timeout() bool {
return true
}
@ -1904,10 +1844,6 @@ func newClientTLSConfig(c *tls.Config, addr string) *tls.Config {
c = c.Clone()
}
if c.ClientSessionCache == nil {
c.ClientSessionCache = tls.NewLRUClientSessionCache(0)
}
if len(c.ServerName) == 0 {
serverName := tlsServerName(addr)
if serverName == "*" {
@ -2040,7 +1976,11 @@ func dialAddr(addr string, dial DialFunc, dialDualStack, isTLS bool, tlsConfig *
if conn == nil {
panic("BUG: DialFunc returned (nil, nil)")
}
_, isTLSAlready := conn.(*tls.Conn)
// We assume that any conn that has the Handshake() method is a TLS conn already.
// This doesn't cover just tls.Conn but also other TLS implementations.
_, isTLSAlready := conn.(interface{ Handshake() error })
if isTLS && !isTLSAlready {
if timeout == 0 {
return tls.Client(conn, tlsConfig), nil

View File

@ -127,11 +127,11 @@ var (
//
// Supported compression levels are:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func AppendGzipBytesLevel(dst, src []byte, level int) []byte {
w := &byteSliceWriter{dst}
WriteGzipLevel(w, src, level) //nolint:errcheck
@ -143,11 +143,11 @@ func AppendGzipBytesLevel(dst, src []byte, level int) []byte {
//
// Supported compression levels are:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func WriteGzipLevel(w io.Writer, p []byte, level int) (int, error) {
switch w.(type) {
case *byteSliceWriter,
@ -223,11 +223,11 @@ func AppendGunzipBytes(dst, src []byte) ([]byte, error) {
//
// Supported compression levels are:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func AppendDeflateBytesLevel(dst, src []byte, level int) []byte {
w := &byteSliceWriter{dst}
WriteDeflateLevel(w, src, level) //nolint:errcheck
@ -239,11 +239,11 @@ func AppendDeflateBytesLevel(dst, src []byte, level int) []byte {
//
// Supported compression levels are:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func WriteDeflateLevel(w io.Writer, p []byte, level int) (int, error) {
switch w.(type) {
case *byteSliceWriter,

View File

@ -3,35 +3,53 @@ Package fasthttp provides fast HTTP server and client API.
Fasthttp provides the following features:
* Optimized for speed. Easily handles more than 100K qps and more than 1M
concurrent keep-alive connections on modern hardware.
* Optimized for low memory usage.
* Easy 'Connection: Upgrade' support via RequestCtx.Hijack.
* Server provides the following anti-DoS limits:
1. Optimized for speed. Easily handles more than 100K qps and more than 1M
concurrent keep-alive connections on modern hardware.
* The number of concurrent connections.
* The number of concurrent connections per client IP.
* The number of requests per connection.
* Request read timeout.
* Response write timeout.
* Maximum request header size.
* Maximum request body size.
* Maximum request execution time.
* Maximum keep-alive connection lifetime.
* Early filtering out non-GET requests.
2. Optimized for low memory usage.
* A lot of additional useful info is exposed to request handler:
3. Easy 'Connection: Upgrade' support via RequestCtx.Hijack.
* Server and client address.
* Per-request logger.
* Unique request id.
* Request start time.
* Connection start time.
* Request sequence number for the current connection.
4. Server provides the following anti-DoS limits:
* Client supports automatic retry on idempotent requests' failure.
* Fasthttp API is designed with the ability to extend existing client
and server implementations or to write custom client and server
implementations from scratch.
- The number of concurrent connections.
- The number of concurrent connections per client IP.
- The number of requests per connection.
- Request read timeout.
- Response write timeout.
- Maximum request header size.
- Maximum request body size.
- Maximum request execution time.
- Maximum keep-alive connection lifetime.
- Early filtering out non-GET requests.
5. A lot of additional useful info is exposed to request handler:
- Server and client address.
- Per-request logger.
- Unique request id.
- Request start time.
- Connection start time.
- Request sequence number for the current connection.
6. Client supports automatic retry on idempotent requests' failure.
7. Fasthttp API is designed with the ability to extend existing client
and server implementations or to write custom client and server
implementations from scratch.
*/
package fasthttp

View File

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBpQbZ6a5jL1Yh4wdP6yZk4MKjYWArD/QOLENFw8vbELoAoGCCqGSM49
AwEHoUQDQgAEKQCZWgE2IBhb47ot8MIs1D4KSisHYlZ41IWyeutpjb0fjwwIhimh
pl1Qld1/d2j3Z3vVyfa5yD+ncV7qCFZuSg==
-----END EC PRIVATE KEY-----

View File

@ -1,10 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBbTCCAROgAwIBAgIQPo718S+K+G7hc1SgTEU4QDAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE3MDQyMDIxMDExNFoXDTE4MDQyMDIxMDExNFow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCkA
mVoBNiAYW+O6LfDCLNQ+CkorB2JWeNSFsnrraY29H48MCIYpoaZdUJXdf3do92d7
1cn2ucg/p3Fe6ghWbkqjSzBJMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggq
hkjOPQQDAgNIADBFAiEAoLAIQkvSuIcHUqyWroA6yWYw2fznlRH/uO9/hMCxUCEC
IClRYb/5O9eD/Eq/ozPnwNpsQHOeYefEhadJ/P82y0lG
-----END CERTIFICATE-----

View File

@ -35,10 +35,10 @@ func NewPipeConns() *PipeConns {
// PipeConns has the following additional features comparing to connections
// returned from net.Pipe():
//
// * It is faster.
// * It buffers Write calls, so there is no need to have concurrent goroutine
// - It is faster.
// - It buffers Write calls, so there is no need to have concurrent goroutine
// calling Read in order to unblock each Write call.
// * It supports read and write deadlines.
// - It supports read and write deadlines.
//
// PipeConns is NOT safe for concurrent use by multiple goroutines!
type PipeConns struct {
@ -209,7 +209,7 @@ func (e *timeoutError) Error() string {
// Only implement the Timeout() function of the net.Error interface.
// This allows for checks like:
//
// if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
// if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
func (e *timeoutError) Timeout() bool {
return true
}

View File

@ -61,8 +61,8 @@ func ServeFileUncompressed(ctx *RequestCtx, path string) {
//
// HTTP response may contain uncompressed file contents in the following cases:
//
// * Missing 'Accept-Encoding: gzip' request header.
// * No write access to directory containing the file.
// - Missing 'Accept-Encoding: gzip' request header.
// - No write access to directory containing the file.
//
// Directory contents is returned if path points to directory.
//
@ -83,8 +83,8 @@ func ServeFileBytes(ctx *RequestCtx, path []byte) {
//
// HTTP response may contain uncompressed file contents in the following cases:
//
// * Missing 'Accept-Encoding: gzip' request header.
// * No write access to directory containing the file.
// - Missing 'Accept-Encoding: gzip' request header.
// - No write access to directory containing the file.
//
// Directory contents is returned if path points to directory.
//
@ -155,12 +155,11 @@ type PathRewriteFunc func(ctx *RequestCtx) []byte
//
// Examples:
//
// * host=foobar.com, slashesCount=0, original path="/foo/bar".
// - host=foobar.com, slashesCount=0, original path="/foo/bar".
// Resulting path: "/foobar.com/foo/bar"
//
// * host=img.aaa.com, slashesCount=1, original path="/images/123/456.jpg"
// - host=img.aaa.com, slashesCount=1, original path="/images/123/456.jpg"
// Resulting path: "/img.aaa.com/123/456.jpg"
//
func NewVHostPathRewriter(slashesCount int) PathRewriteFunc {
return func(ctx *RequestCtx) []byte {
path := stripLeadingSlashes(ctx.Path(), slashesCount)
@ -189,9 +188,9 @@ var strInvalidHost = []byte("invalid-host")
//
// Examples:
//
// * slashesCount = 0, original path: "/foo/bar", result: "/foo/bar"
// * slashesCount = 1, original path: "/foo/bar", result: "/bar"
// * slashesCount = 2, original path: "/foo/bar", result: ""
// - slashesCount = 0, original path: "/foo/bar", result: "/foo/bar"
// - slashesCount = 1, original path: "/foo/bar", result: "/bar"
// - slashesCount = 2, original path: "/foo/bar", result: ""
//
// The returned path rewriter may be used as FS.PathRewrite .
func NewPathSlashesStripper(slashesCount int) PathRewriteFunc {
@ -205,9 +204,9 @@ func NewPathSlashesStripper(slashesCount int) PathRewriteFunc {
//
// Examples:
//
// * prefixSize = 0, original path: "/foo/bar", result: "/foo/bar"
// * prefixSize = 3, original path: "/foo/bar", result: "o/bar"
// * prefixSize = 7, original path: "/foo/bar", result: "r"
// - prefixSize = 0, original path: "/foo/bar", result: "/foo/bar"
// - prefixSize = 3, original path: "/foo/bar", result: "o/bar"
// - prefixSize = 7, original path: "/foo/bar", result: "r"
//
// The returned path rewriter may be used as FS.PathRewrite .
func NewPathPrefixStripper(prefixSize int) PathRewriteFunc {
@ -276,6 +275,10 @@ type FS struct {
// Brotli encoding is disabled by default.
CompressBrotli bool
// Path to the compressed root directory to serve files from. If this value
// is empty, Root is used.
CompressRoot string
// Enables byte range requests if set to true.
//
// Byte range requests are disabled by default.
@ -346,9 +349,9 @@ const FSHandlerCacheDuration = 10 * time.Second
// from requested path before searching requested file in the root folder.
// Examples:
//
// * stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
// * stripSlashes = 1, original path: "/foo/bar", result: "/bar"
// * stripSlashes = 2, original path: "/foo/bar", result: ""
// - stripSlashes = 0, original path: "/foo/bar", result: "/foo/bar"
// - stripSlashes = 1, original path: "/foo/bar", result: "/bar"
// - stripSlashes = 2, original path: "/foo/bar", result: ""
//
// The returned request handler automatically generates index pages
// for directories without index.html.
@ -388,9 +391,7 @@ func (fs *FS) NewRequestHandler() RequestHandler {
return fs.h
}
func (fs *FS) initRequestHandler() {
root := fs.Root
func (fs *FS) normalizeRoot(root string) string {
// Serve files from the current working directory if Root is empty or if Root is a relative path.
if (!fs.AllowEmptyRoot && len(root) == 0) || (len(root) > 0 && !filepath.IsAbs(root)) {
path, err := os.Getwd()
@ -406,6 +407,18 @@ func (fs *FS) initRequestHandler() {
for len(root) > 0 && root[len(root)-1] == os.PathSeparator {
root = root[:len(root)-1]
}
return root
}
func (fs *FS) initRequestHandler() {
root := fs.normalizeRoot(fs.Root)
compressRoot := fs.CompressRoot
if len(compressRoot) == 0 {
compressRoot = root
} else {
compressRoot = fs.normalizeRoot(compressRoot)
}
cacheDuration := fs.CacheDuration
if cacheDuration <= 0 {
@ -430,6 +443,7 @@ func (fs *FS) initRequestHandler() {
generateIndexPages: fs.GenerateIndexPages,
compress: fs.Compress,
compressBrotli: fs.CompressBrotli,
compressRoot: compressRoot,
pathNotFound: fs.PathNotFound,
acceptByteRange: fs.AcceptByteRange,
cacheDuration: cacheDuration,
@ -478,6 +492,7 @@ type fsHandler struct {
generateIndexPages bool
compress bool
compressBrotli bool
compressRoot string
acceptByteRange bool
cacheDuration time.Duration
compressedFileSuffixes map[string]string
@ -780,6 +795,20 @@ func cleanCacheNolock(cache map[string]*fsFile, pendingFiles, filesToRelease []*
return pendingFiles, filesToRelease
}
func (h *fsHandler) pathToFilePath(path string) string {
return filepath.FromSlash(h.root + path)
}
func (h *fsHandler) filePathToCompressed(filePath string) string {
if h.root == h.compressRoot {
return filePath
}
if !strings.HasPrefix(filePath, h.root) {
return filePath
}
return filepath.FromSlash(h.compressRoot + filePath[len(h.root):])
}
func (h *fsHandler) handleRequest(ctx *RequestCtx) {
var path []byte
if h.pathRewrite != nil {
@ -831,7 +860,7 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
if !ok {
pathStr := string(path)
filePath := filepath.FromSlash(h.root + pathStr)
filePath := h.pathToFilePath(pathStr)
var err error
ff, err = h.openFSFile(filePath, mustCompress, fileEncoding)
@ -1153,7 +1182,14 @@ func (h *fsHandler) compressAndOpenFSFile(filePath string, fileEncoding string)
return h.newFSFile(f, fileInfo, false, "")
}
compressedFilePath := filePath + h.compressedFileSuffixes[fileEncoding]
compressedFilePath := h.filePathToCompressed(filePath)
if compressedFilePath != filePath {
if err := os.MkdirAll(filepath.Dir(compressedFilePath), os.ModePerm); err != nil {
return nil, err
}
}
compressedFilePath += h.compressedFileSuffixes[fileEncoding]
absPath, err := filepath.Abs(compressedFilePath)
if err != nil {
_ = f.Close()

View File

@ -109,8 +109,8 @@ func (h *ResponseHeader) SetContentRange(startPos, endPos, contentLength int) {
// SetByteRange sets 'Range: bytes=startPos-endPos' header.
//
// * If startPos is negative, then 'bytes=-startPos' value is set.
// * If endPos is negative, then 'bytes=startPos-' value is set.
// - If startPos is negative, then 'bytes=-startPos' value is set.
// - If endPos is negative, then 'bytes=startPos-' value is set.
func (h *RequestHeader) SetByteRange(startPos, endPos int) {
b := h.bufKV.value[:0]
b = append(b, strBytes...)
@ -868,7 +868,7 @@ func (h *RequestHeader) HasAcceptEncodingBytes(acceptEncoding []byte) bool {
// i.e. the number of times f is called in VisitAll.
func (h *ResponseHeader) Len() int {
n := 0
h.VisitAll(func(k, v []byte) { n++ })
h.VisitAll(func(_, _ []byte) { n++ })
return n
}
@ -876,7 +876,7 @@ func (h *ResponseHeader) Len() int {
// i.e. the number of times f is called in VisitAll.
func (h *RequestHeader) Len() int {
n := 0
h.VisitAll(func(k, v []byte) { n++ })
h.VisitAll(func(_, _ []byte) { n++ })
return n
}
@ -887,9 +887,9 @@ func (h *RequestHeader) Len() int {
// while lowercasing all the other letters.
// Examples:
//
// * CONNECTION -> Connection
// * conteNT-tYPE -> Content-Type
// * foo-bar-baz -> Foo-Bar-Baz
// - CONNECTION -> Connection
// - conteNT-tYPE -> Content-Type
// - foo-bar-baz -> Foo-Bar-Baz
//
// Disable header names' normalization only if know what are you doing.
func (h *RequestHeader) DisableNormalizing() {
@ -903,9 +903,9 @@ func (h *RequestHeader) DisableNormalizing() {
// the other letters.
// Examples:
//
// * CONNECTION -> Connection
// * conteNT-tYPE -> Content-Type
// * foo-bar-baz -> Foo-Bar-Baz
// - CONNECTION -> Connection
// - conteNT-tYPE -> Content-Type
// - foo-bar-baz -> Foo-Bar-Baz
//
// This is enabled by default unless disabled using DisableNormalizing()
func (h *RequestHeader) EnableNormalizing() {
@ -919,9 +919,9 @@ func (h *RequestHeader) EnableNormalizing() {
// while lowercasing all the other letters.
// Examples:
//
// * CONNECTION -> Connection
// * conteNT-tYPE -> Content-Type
// * foo-bar-baz -> Foo-Bar-Baz
// - CONNECTION -> Connection
// - conteNT-tYPE -> Content-Type
// - foo-bar-baz -> Foo-Bar-Baz
//
// Disable header names' normalization only if know what are you doing.
func (h *ResponseHeader) DisableNormalizing() {
@ -935,9 +935,9 @@ func (h *ResponseHeader) DisableNormalizing() {
// the other letters.
// Examples:
//
// * CONNECTION -> Connection
// * conteNT-tYPE -> Content-Type
// * foo-bar-baz -> Foo-Bar-Baz
// - CONNECTION -> Connection
// - conteNT-tYPE -> Content-Type
// - foo-bar-baz -> Foo-Bar-Baz
//
// This is enabled by default unless disabled using DisableNormalizing()
func (h *ResponseHeader) EnableNormalizing() {
@ -1077,7 +1077,7 @@ func (h *ResponseHeader) VisitAll(f func(key, value []byte)) {
f(strServer, server)
}
if len(h.cookies) > 0 {
visitArgs(h.cookies, func(k, v []byte) {
visitArgs(h.cookies, func(_, v []byte) {
f(strSetCookie, v)
})
}
@ -1516,13 +1516,13 @@ func (h *RequestHeader) SetCookieBytesKV(key, value []byte) {
// This doesn't work for a cookie with specific domain or path,
// you should delete it manually like:
//
// c := AcquireCookie()
// c.SetKey(key)
// c.SetDomain("example.com")
// c.SetPath("/path")
// c.SetExpire(CookieExpireDelete)
// h.SetCookie(c)
// ReleaseCookie(c)
// c := AcquireCookie()
// c.SetKey(key)
// c.SetDomain("example.com")
// c.SetPath("/path")
// c.SetExpire(CookieExpireDelete)
// h.SetCookie(c)
// ReleaseCookie(c)
//
// Use DelCookie if you want just removing the cookie from response header.
func (h *ResponseHeader) DelClientCookie(key string) {
@ -1539,13 +1539,13 @@ func (h *ResponseHeader) DelClientCookie(key string) {
// This doesn't work for a cookie with specific domain or path,
// you should delete it manually like:
//
// c := AcquireCookie()
// c.SetKey(key)
// c.SetDomain("example.com")
// c.SetPath("/path")
// c.SetExpire(CookieExpireDelete)
// h.SetCookie(c)
// ReleaseCookie(c)
// c := AcquireCookie()
// c.SetKey(key)
// c.SetDomain("example.com")
// c.SetPath("/path")
// c.SetExpire(CookieExpireDelete)
// h.SetCookie(c)
// ReleaseCookie(c)
//
// Use DelCookieBytes if you want just removing the cookie from response header.
func (h *ResponseHeader) DelClientCookieBytes(key []byte) {
@ -3176,9 +3176,9 @@ func removeNewLines(raw []byte) []byte {
// after dashes are also uppercased. All the other letters are lowercased.
// Examples:
//
// * coNTENT-TYPe -> Content-Type
// * HOST -> Host
// * foo-bar-baz -> Foo-Bar-Baz
// - coNTENT-TYPe -> Content-Type
// - HOST -> Host
// - foo-bar-baz -> Foo-Bar-Baz
func AppendNormalizedHeaderKey(dst []byte, key string) []byte {
dst = append(dst, key...)
normalizeHeaderKey(dst[len(dst)-len(key):], false)
@ -3192,9 +3192,9 @@ func AppendNormalizedHeaderKey(dst []byte, key string) []byte {
// after dashes are also uppercased. All the other letters are lowercased.
// Examples:
//
// * coNTENT-TYPe -> Content-Type
// * HOST -> Host
// * foo-bar-baz -> Foo-Bar-Baz
// - coNTENT-TYPe -> Content-Type
// - HOST -> Host
// - foo-bar-baz -> Foo-Bar-Baz
func AppendNormalizedHeaderKeyBytes(dst, key []byte) []byte {
return AppendNormalizedHeaderKey(dst, b2s(key))
}

View File

@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"math"
"mime/multipart"
"net"
"os"
@ -254,9 +255,9 @@ func (resp *Response) IsBodyStream() bool {
//
// This function may be used in the following cases:
//
// * if request body is too big (more than 10MB).
// * if request body is streamed from slow external sources.
// * if request body must be streamed to the server in chunks
// - if request body is too big (more than 10MB).
// - if request body is streamed from slow external sources.
// - if request body must be streamed to the server in chunks
// (aka `http client push` or `chunked transfer-encoding`).
//
// Note that GET and HEAD requests cannot have body.
@ -271,9 +272,9 @@ func (req *Request) SetBodyStreamWriter(sw StreamWriter) {
//
// This function may be used in the following cases:
//
// * if response body is too big (more than 10MB).
// * if response body is streamed from slow external sources.
// * if response body must be streamed to the client in chunks
// - if response body is too big (more than 10MB).
// - if response body is streamed from slow external sources.
// - if response body must be streamed to the client in chunks
// (aka `http server push` or `chunked transfer-encoding`).
//
// See also SetBodyStream.
@ -1080,11 +1081,11 @@ func (resp *Response) resetSkipHeader() {
//
// If MayContinue returns true, the caller must:
//
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
//
// io.EOF is returned if r is closed before reading the first header byte.
func (req *Request) Read(r *bufio.Reader) error {
@ -1108,11 +1109,11 @@ var ErrGetOnly = errors.New("non-GET request received")
//
// If MayContinue returns true, the caller must:
//
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
//
// io.EOF is returned if r is closed before reading the first header byte.
func (req *Request) ReadLimitBody(r *bufio.Reader, maxBodySize int) error {
@ -1165,11 +1166,11 @@ func (req *Request) readBodyStream(r *bufio.Reader, maxBodySize int, getOnly boo
//
// The caller must do one of the following actions if MayContinue returns true:
//
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
// - Either send StatusExpectationFailed response if request headers don't
// satisfy the caller.
// - Or send StatusContinue response before reading request body
// with ContinueReadBody.
// - Or close the connection.
func (req *Request) MayContinue() bool {
return bytes.Equal(req.Header.peek(strExpect), str100Continue)
}
@ -1561,11 +1562,11 @@ func (resp *Response) WriteGzip(w *bufio.Writer) error {
//
// Level is the desired compression level:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
//
// The method gzips response body and sets 'Content-Encoding: gzip'
// header before writing response to w.
@ -1592,11 +1593,11 @@ func (resp *Response) WriteDeflate(w *bufio.Writer) error {
//
// Level is the desired compression level:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
//
// The method deflates response body and sets 'Content-Encoding: deflate'
// header before writing response to w.
@ -2278,5 +2279,10 @@ func round2(n int) int {
x |= x >> 8
x |= x >> 16
// Make sure we don't return 0 due to overflow, even on 32 bit systems
if x >= uint32(math.MaxInt32) {
return math.MaxInt32
}
return int(x + 1)
}

View File

@ -48,8 +48,10 @@ type perIPConn struct {
func acquirePerIPConn(conn net.Conn, ip uint32, counter *perIPConnCounter) *perIPConn {
v := counter.pool.Get()
if v == nil {
v = &perIPConn{
return &perIPConn{
perIPConnCounter: counter,
Conn: conn,
ip: ip,
}
}
c := v.(*perIPConn)

View File

@ -421,7 +421,7 @@ type Server struct {
// We need to know our listeners and idle connections so we can close them in Shutdown().
ln []net.Listener
idleConns map[net.Conn]struct{}
idleConns map[net.Conn]time.Time
idleConnsMu sync.Mutex
mu sync.Mutex
@ -510,11 +510,11 @@ func CompressHandler(h RequestHandler) RequestHandler {
//
// Level is the desired compression level:
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func CompressHandlerLevel(h RequestHandler, level int) RequestHandler {
return func(ctx *RequestCtx) {
h(ctx)
@ -532,18 +532,18 @@ func CompressHandlerLevel(h RequestHandler, level int) RequestHandler {
//
// brotliLevel is the desired compression level for brotli.
//
// * CompressBrotliNoCompression
// * CompressBrotliBestSpeed
// * CompressBrotliBestCompression
// * CompressBrotliDefaultCompression
// - CompressBrotliNoCompression
// - CompressBrotliBestSpeed
// - CompressBrotliBestCompression
// - CompressBrotliDefaultCompression
//
// otherLevel is the desired compression level for gzip and deflate.
//
// * CompressNoCompression
// * CompressBestSpeed
// * CompressBestCompression
// * CompressDefaultCompression
// * CompressHuffmanOnly
// - CompressNoCompression
// - CompressBestSpeed
// - CompressBestCompression
// - CompressDefaultCompression
// - CompressHuffmanOnly
func CompressHandlerBrotliLevel(h RequestHandler, brotliLevel, otherLevel int) RequestHandler {
return func(ctx *RequestCtx) {
h(ctx)
@ -626,8 +626,8 @@ type HijackHandler func(c net.Conn)
//
// The server skips calling the handler in the following cases:
//
// * 'Connection: close' header exists in either request or response.
// * Unexpected error during response writing to the connection.
// - 'Connection: close' header exists in either request or response.
// - Unexpected error during response writing to the connection.
//
// The server stops processing requests from hijacked connections.
//
@ -639,9 +639,8 @@ type HijackHandler func(c net.Conn)
// Arbitrary 'Connection: Upgrade' protocols may be implemented
// with HijackHandler. For instance,
//
// * WebSocket ( https://en.wikipedia.org/wiki/WebSocket )
// * HTTP/2.0 ( https://en.wikipedia.org/wiki/HTTP/2 )
//
// - WebSocket ( https://en.wikipedia.org/wiki/WebSocket )
// - HTTP/2.0 ( https://en.wikipedia.org/wiki/HTTP/2 )
func (ctx *RequestCtx) Hijack(handler HijackHandler) {
ctx.hijackHandler = handler
}
@ -1084,15 +1083,15 @@ func SaveMultipartFile(fh *multipart.FileHeader, path string) (err error) {
//
// The value is searched in the following places:
//
// * Query string.
// * POST or PUT body.
// - Query string.
// - POST or PUT body.
//
// There are more fine-grained methods for obtaining form values:
//
// * QueryArgs for obtaining values from query string.
// * PostArgs for obtaining values from POST or PUT body.
// * MultipartForm for obtaining values from multipart form.
// * FormFile for obtaining uploaded files.
// - QueryArgs for obtaining values from query string.
// - PostArgs for obtaining values from POST or PUT body.
// - MultipartForm for obtaining values from multipart form.
// - FormFile for obtaining uploaded files.
//
// The returned value is valid until your request handler returns.
func (ctx *RequestCtx) FormValue(key string) []byte {
@ -1254,11 +1253,11 @@ func (ctx *RequestCtx) SuccessString(contentType, body string) {
//
// statusCode must have one of the following values:
//
// * StatusMovedPermanently (301)
// * StatusFound (302)
// * StatusSeeOther (303)
// * StatusTemporaryRedirect (307)
// * StatusPermanentRedirect (308)
// - StatusMovedPermanently (301)
// - StatusFound (302)
// - StatusSeeOther (303)
// - StatusTemporaryRedirect (307)
// - StatusPermanentRedirect (308)
//
// All other statusCode values are replaced by StatusFound (302).
//
@ -1266,10 +1265,9 @@ func (ctx *RequestCtx) SuccessString(contentType, body string) {
// request uri. Fasthttp will always send an absolute uri back to the client.
// To send a relative uri you can use the following code:
//
// strLocation = []byte("Location") // Put this with your top level var () declarations.
// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
//
// strLocation = []byte("Location") // Put this with your top level var () declarations.
// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
func (ctx *RequestCtx) Redirect(uri string, statusCode int) {
u := AcquireURI()
ctx.URI().CopyTo(u)
@ -1283,11 +1281,11 @@ func (ctx *RequestCtx) Redirect(uri string, statusCode int) {
//
// statusCode must have one of the following values:
//
// * StatusMovedPermanently (301)
// * StatusFound (302)
// * StatusSeeOther (303)
// * StatusTemporaryRedirect (307)
// * StatusPermanentRedirect (308)
// - StatusMovedPermanently (301)
// - StatusFound (302)
// - StatusSeeOther (303)
// - StatusTemporaryRedirect (307)
// - StatusPermanentRedirect (308)
//
// All other statusCode values are replaced by StatusFound (302).
//
@ -1295,10 +1293,9 @@ func (ctx *RequestCtx) Redirect(uri string, statusCode int) {
// request uri. Fasthttp will always send an absolute uri back to the client.
// To send a relative uri you can use the following code:
//
// strLocation = []byte("Location") // Put this with your top level var () declarations.
// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
//
// strLocation = []byte("Location") // Put this with your top level var () declarations.
// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
func (ctx *RequestCtx) RedirectBytes(uri []byte, statusCode int) {
s := b2s(uri)
ctx.Redirect(s, statusCode)
@ -1437,9 +1434,9 @@ func (ctx *RequestCtx) SetBodyStream(bodyStream io.Reader, bodySize int) {
//
// This function may be used in the following cases:
//
// * if response body is too big (more than 10MB).
// * if response body is streamed from slow external sources.
// * if response body must be streamed to the client in chunks.
// - if response body is too big (more than 10MB).
// - if response body is streamed from slow external sources.
// - if response body must be streamed to the client in chunks.
// (aka `http server push`).
func (ctx *RequestCtx) SetBodyStreamWriter(sw StreamWriter) {
ctx.Response.SetBodyStreamWriter(sw)
@ -1839,12 +1836,12 @@ func (s *Server) Shutdown() error {
close(s.done)
}
s.closeIdleConns()
// Closing the listener will make Serve() call Stop on the worker pool.
// Setting .stop to 1 will make serveConn() break out of its loop.
// Now we just have to wait until all workers are done.
for {
s.closeIdleConns()
if open := atomic.LoadInt32(&s.open); open == 0 {
break
}
@ -1864,21 +1861,21 @@ func acceptConn(s *Server, ln net.Listener, lastPerIPErrorTime *time.Time) (net.
var c net.Conn
var err error
if tl, ok := ln.(*net.TCPListener); ok && s.TCPKeepalive {
tc, err := tl.AcceptTCP()
if err != nil {
return nil, err
}
if err := tc.SetKeepAlive(s.TCPKeepalive); err != nil {
tc.Close() //nolint:errcheck
return nil, err
}
if s.TCPKeepalivePeriod > 0 {
if err := tc.SetKeepAlivePeriod(s.TCPKeepalivePeriod); err != nil {
var tc *net.TCPConn
tc, err = tl.AcceptTCP()
if err == nil {
if err := tc.SetKeepAlive(s.TCPKeepalive); err != nil {
tc.Close() //nolint:errcheck
return nil, err
}
if s.TCPKeepalivePeriod > 0 {
if err := tc.SetKeepAlivePeriod(s.TCPKeepalivePeriod); err != nil {
tc.Close() //nolint:errcheck
return nil, err
}
}
c = tc
}
c = tc
} else {
c, err = ln.Accept()
}
@ -2197,9 +2194,15 @@ func (s *Server) serveConn(c net.Conn) (err error) {
}
if reqConf.MaxRequestBodySize > 0 {
maxRequestBodySize = reqConf.MaxRequestBodySize
} else if s.MaxRequestBodySize > 0 {
maxRequestBodySize = s.MaxRequestBodySize
} else {
maxRequestBodySize = DefaultMaxRequestBodySize
}
if reqConf.WriteTimeout > 0 {
writeTimeout = reqConf.WriteTimeout
} else {
writeTimeout = s.WriteTimeout
}
}
// read body
@ -2816,9 +2819,16 @@ func (s *Server) trackConn(c net.Conn, state ConnState) {
switch state {
case StateIdle:
if s.idleConns == nil {
s.idleConns = make(map[net.Conn]struct{})
s.idleConns = make(map[net.Conn]time.Time)
}
s.idleConns[c] = struct{}{}
s.idleConns[c] = time.Now()
case StateNew:
if s.idleConns == nil {
s.idleConns = make(map[net.Conn]time.Time)
}
// Count the connection as Idle after 5 seconds.
// Same as net/http.Server: https://github.com/golang/go/blob/85d7bab91d9a3ed1f76842e4328973ea75efef54/src/net/http/server.go#L2834-L2836
s.idleConns[c] = time.Now().Add(time.Second * 5)
default:
delete(s.idleConns, c)
@ -2828,10 +2838,13 @@ func (s *Server) trackConn(c net.Conn, state ConnState) {
func (s *Server) closeIdleConns() {
s.idleConnsMu.Lock()
for c := range s.idleConns {
_ = c.Close()
now := time.Now()
for c, t := range s.idleConns {
if now.Sub(t) >= 0 {
_ = c.Close()
delete(s.idleConns, c)
}
}
s.idleConns = nil
s.idleConnsMu.Unlock()
}

View File

@ -12,9 +12,9 @@ import (
// The wrapper may save a lot of stack space if the following conditions
// are met:
//
// - f doesn't contain blocking calls on network, I/O or channels;
// - f uses a lot of stack space;
// - the wrapper is called from high number of concurrent goroutines.
// - f doesn't contain blocking calls on network, I/O or channels;
// - f uses a lot of stack space;
// - the wrapper is called from high number of concurrent goroutines.
//
// The stackless wrapper returns false if the call cannot be processed
// at the moment due to high load.

View File

@ -14,12 +14,12 @@ import (
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
// * It returns ErrDialTimeout if connection cannot be established during
// - It returns ErrDialTimeout if connection cannot be established during
// DefaultDialTimeout seconds. Use DialTimeout for customizing dial timeout.
//
// This dialer is intended for custom code wrapping before passing
@ -30,9 +30,9 @@ import (
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func Dial(addr string) (net.Conn, error) {
return defaultDialer.Dial(addr)
}
@ -41,9 +41,9 @@ func Dial(addr string) (net.Conn, error) {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
//
@ -55,9 +55,9 @@ func Dial(addr string) (net.Conn, error) {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
return defaultDialer.DialTimeout(addr, timeout)
}
@ -66,12 +66,12 @@ func DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
// * It returns ErrDialTimeout if connection cannot be established during
// - It returns ErrDialTimeout if connection cannot be established during
// DefaultDialTimeout seconds. Use DialDualStackTimeout for custom dial
// timeout.
//
@ -83,9 +83,9 @@ func DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func DialDualStack(addr string) (net.Conn, error) {
return defaultDialer.DialDualStack(addr)
}
@ -95,9 +95,9 @@ func DialDualStack(addr string) (net.Conn, error) {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
//
@ -109,9 +109,9 @@ func DialDualStack(addr string) (net.Conn, error) {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func DialDualStackTimeout(addr string, timeout time.Duration) (net.Conn, error) {
return defaultDialer.DialDualStackTimeout(addr, timeout)
}
@ -167,12 +167,12 @@ type TCPDialer struct {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
// * It returns ErrDialTimeout if connection cannot be established during
// - It returns ErrDialTimeout if connection cannot be established during
// DefaultDialTimeout seconds. Use DialTimeout for customizing dial timeout.
//
// This dialer is intended for custom code wrapping before passing
@ -183,9 +183,9 @@ type TCPDialer struct {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func (d *TCPDialer) Dial(addr string) (net.Conn, error) {
return d.dial(addr, false, DefaultDialTimeout)
}
@ -194,9 +194,9 @@ func (d *TCPDialer) Dial(addr string) (net.Conn, error) {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
//
@ -208,9 +208,9 @@ func (d *TCPDialer) Dial(addr string) (net.Conn, error) {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func (d *TCPDialer) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
return d.dial(addr, false, timeout)
}
@ -219,12 +219,12 @@ func (d *TCPDialer) DialTimeout(addr string, timeout time.Duration) (net.Conn, e
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
// * It returns ErrDialTimeout if connection cannot be established during
// - It returns ErrDialTimeout if connection cannot be established during
// DefaultDialTimeout seconds. Use DialDualStackTimeout for custom dial
// timeout.
//
@ -236,9 +236,9 @@ func (d *TCPDialer) DialTimeout(addr string, timeout time.Duration) (net.Conn, e
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func (d *TCPDialer) DialDualStack(addr string) (net.Conn, error) {
return d.dial(addr, true, DefaultDialTimeout)
}
@ -248,9 +248,9 @@ func (d *TCPDialer) DialDualStack(addr string) (net.Conn, error) {
//
// This function has the following additional features comparing to net.Dial:
//
// * It reduces load on DNS resolver by caching resolved TCP addressed
// - It reduces load on DNS resolver by caching resolved TCP addressed
// for DNSCacheDuration.
// * It dials all the resolved TCP addresses in round-robin manner until
// - It dials all the resolved TCP addresses in round-robin manner until
// connection is established. This may be useful if certain addresses
// are temporarily unreachable.
//
@ -262,9 +262,9 @@ func (d *TCPDialer) DialDualStack(addr string) (net.Conn, error) {
//
// The addr passed to the function must contain port. Example addr values:
//
// * foobar.baz:443
// * foo.bar:80
// * aaa.com:8080
// - foobar.baz:443
// - foo.bar:80
// - aaa.com:8080
func (d *TCPDialer) DialDualStackTimeout(addr string, timeout time.Duration) (net.Conn, error) {
return d.dial(addr, true, timeout)
}

View File

@ -538,15 +538,9 @@ func shouldEscape(c byte, mode encoding) bool {
}
func ishex(c byte) bool {
switch {
case '0' <= c && c <= '9':
return true
case 'a' <= c && c <= 'f':
return true
case 'A' <= c && c <= 'F':
return true
}
return false
return ('0' <= c && c <= '9') ||
('a' <= c && c <= 'f') ||
('A' <= c && c <= 'F')
}
func unhex(c byte) byte {
@ -715,9 +709,9 @@ func (u *URI) RequestURI() []byte {
//
// Examples:
//
// * For /foo/bar/baz.html path returns baz.html.
// * For /foo/bar/ returns empty byte slice.
// * For /foobar.js returns foobar.js.
// - For /foo/bar/baz.html path returns baz.html.
// - For /foo/bar/ returns empty byte slice.
// - For /foobar.js returns foobar.js.
//
// The returned bytes are valid until the next URI method call.
func (u *URI) LastPathSegment() []byte {
@ -733,14 +727,14 @@ func (u *URI) LastPathSegment() []byte {
//
// The following newURI types are accepted:
//
// * Absolute, i.e. http://foobar.com/aaa/bb?cc . In this case the original
// uri is replaced by newURI.
// * Absolute without scheme, i.e. //foobar.com/aaa/bb?cc. In this case
// the original scheme is preserved.
// * Missing host, i.e. /aaa/bb?cc . In this case only RequestURI part
// of the original uri is replaced.
// * Relative path, i.e. xx?yy=abc . In this case the original RequestURI
// is updated according to the new relative path.
// - Absolute, i.e. http://foobar.com/aaa/bb?cc . In this case the original
// uri is replaced by newURI.
// - Absolute without scheme, i.e. //foobar.com/aaa/bb?cc. In this case
// the original scheme is preserved.
// - Missing host, i.e. /aaa/bb?cc . In this case only RequestURI part
// of the original uri is replaced.
// - Relative path, i.e. xx?yy=abc . In this case the original RequestURI
// is updated according to the new relative path.
func (u *URI) Update(newURI string) {
u.UpdateBytes(s2b(newURI))
}
@ -749,14 +743,14 @@ func (u *URI) Update(newURI string) {
//
// The following newURI types are accepted:
//
// * Absolute, i.e. http://foobar.com/aaa/bb?cc . In this case the original
// uri is replaced by newURI.
// * Absolute without scheme, i.e. //foobar.com/aaa/bb?cc. In this case
// the original scheme is preserved.
// * Missing host, i.e. /aaa/bb?cc . In this case only RequestURI part
// of the original uri is replaced.
// * Relative path, i.e. xx?yy=abc . In this case the original RequestURI
// is updated according to the new relative path.
// - Absolute, i.e. http://foobar.com/aaa/bb?cc . In this case the original
// uri is replaced by newURI.
// - Absolute without scheme, i.e. //foobar.com/aaa/bb?cc. In this case
// the original scheme is preserved.
// - Missing host, i.e. /aaa/bb?cc . In this case only RequestURI part
// of the original uri is replaced.
// - Relative path, i.e. xx?yy=abc . In this case the original RequestURI
// is updated according to the new relative path.
func (u *URI) UpdateBytes(newURI []byte) {
u.requestURI = u.updateBytes(newURI, u.requestURI)
}

4
vendor/modules.txt vendored
View File

@ -378,7 +378,7 @@ github.com/modern-go/reflect2
# github.com/nickname76/repeater v1.0.1
## explicit; go 1.18
github.com/nickname76/repeater
# github.com/nickname76/telegrambot v1.2.1
# github.com/nickname76/telegrambot v1.2.2
## explicit; go 1.18
github.com/nickname76/telegrambot
# github.com/nicksnyder/go-i18n/v2 v2.2.0 => github.com/tyrm/go-i18n/v2 v2.0.0-20220816225026-eff1682f19d0
@ -490,7 +490,7 @@ github.com/uptrace/uptrace-go/uptrace
# github.com/valyala/bytebufferpool v1.0.0
## explicit
github.com/valyala/bytebufferpool
# github.com/valyala/fasthttp v1.38.0
# github.com/valyala/fasthttp v1.40.0
## explicit; go 1.15
github.com/valyala/fasthttp
github.com/valyala/fasthttp/fasthttputil