mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore]: Bump github.com/gin-contrib/gzip from 1.1.0 to 1.2.2 (#3693)
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.1.0 to 1.2.2. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.1.0...v1.2.2) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... 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:
41
vendor/github.com/gin-contrib/gzip/README.md
generated
vendored
41
vendor/github.com/gin-contrib/gzip/README.md
generated
vendored
@ -49,7 +49,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Customized Excluded Extensions
|
||||
### Customized Excluded Extensions
|
||||
|
||||
```go
|
||||
package main
|
||||
@ -77,7 +77,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Customized Excluded Paths
|
||||
### Customized Excluded Paths
|
||||
|
||||
```go
|
||||
package main
|
||||
@ -105,7 +105,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Customized Excluded Paths
|
||||
### Customized Excluded Paths with Regex
|
||||
|
||||
```go
|
||||
package main
|
||||
@ -132,3 +132,38 @@ func main() {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Server Push
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
r.GET("/stream", func(c *gin.Context) {
|
||||
c.Header("Content-Type", "text/event-stream")
|
||||
c.Header("Connection", "keep-alive")
|
||||
for i := 0; i < 10; i++ {
|
||||
fmt.Fprintf(c.Writer, "id: %d\ndata: tick %d\n\n", i, time.Now().Unix())
|
||||
c.Writer.Flush()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
})
|
||||
|
||||
// Listen and Server in 0.0.0.0:8080
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
28
vendor/github.com/gin-contrib/gzip/gzip.go
generated
vendored
28
vendor/github.com/gin-contrib/gzip/gzip.go
generated
vendored
@ -1,7 +1,11 @@
|
||||
package gzip
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@ -11,6 +15,7 @@ const (
|
||||
BestSpeed = gzip.BestSpeed
|
||||
DefaultCompression = gzip.DefaultCompression
|
||||
NoCompression = gzip.NoCompression
|
||||
HuffmanOnly = gzip.HuffmanOnly
|
||||
)
|
||||
|
||||
func Gzip(level int, options ...Option) gin.HandlerFunc {
|
||||
@ -32,8 +37,31 @@ func (g *gzipWriter) Write(data []byte) (int, error) {
|
||||
return g.writer.Write(data)
|
||||
}
|
||||
|
||||
func (g *gzipWriter) Flush() {
|
||||
_ = g.writer.Flush()
|
||||
g.ResponseWriter.Flush()
|
||||
}
|
||||
|
||||
// Fix: https://github.com/mholt/caddy/issues/38
|
||||
func (g *gzipWriter) WriteHeader(code int) {
|
||||
g.Header().Del("Content-Length")
|
||||
g.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
// Ensure gzipWriter implements the http.Hijacker interface.
|
||||
// This will cause a compile-time error if gzipWriter does not implement all methods of the http.Hijacker interface.
|
||||
var _ http.Hijacker = (*gzipWriter)(nil)
|
||||
|
||||
// Hijack allows the caller to take over the connection from the HTTP server.
|
||||
// After a call to Hijack, the HTTP server library will not do anything else with the connection.
|
||||
// It becomes the caller's responsibility to manage and close the connection.
|
||||
//
|
||||
// It returns the underlying net.Conn, a buffered reader/writer for the connection, and an error
|
||||
// if the ResponseWriter does not support the Hijacker interface.
|
||||
func (g *gzipWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
hijacker, ok := g.ResponseWriter.(http.Hijacker)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("the ResponseWriter doesn't support the Hijacker interface")
|
||||
}
|
||||
return hijacker.Hijack()
|
||||
}
|
||||
|
90
vendor/github.com/gin-contrib/gzip/handler.go
generated
vendored
90
vendor/github.com/gin-contrib/gzip/handler.go
generated
vendored
@ -2,84 +2,114 @@ package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
headerAcceptEncoding = "Accept-Encoding"
|
||||
headerContentEncoding = "Content-Encoding"
|
||||
headerVary = "Vary"
|
||||
)
|
||||
|
||||
type gzipHandler struct {
|
||||
*Options
|
||||
*config
|
||||
gzPool sync.Pool
|
||||
}
|
||||
|
||||
func newGzipHandler(level int, options ...Option) *gzipHandler {
|
||||
func isCompressionLevelValid(level int) bool {
|
||||
return level == gzip.DefaultCompression ||
|
||||
level == gzip.NoCompression ||
|
||||
(level >= gzip.BestSpeed && level <= gzip.BestCompression)
|
||||
}
|
||||
|
||||
func newGzipHandler(level int, opts ...Option) *gzipHandler {
|
||||
cfg := &config{
|
||||
excludedExtensions: DefaultExcludedExtentions,
|
||||
}
|
||||
|
||||
// Apply each option to the config
|
||||
for _, o := range opts {
|
||||
o.apply(cfg)
|
||||
}
|
||||
|
||||
if !isCompressionLevelValid(level) {
|
||||
// For web content, level 4 seems to be a sweet spot.
|
||||
level = 4
|
||||
}
|
||||
|
||||
handler := &gzipHandler{
|
||||
Options: DefaultOptions,
|
||||
config: cfg,
|
||||
gzPool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
gz, err := gzip.NewWriterLevel(io.Discard, level)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gz, _ := gzip.NewWriterLevel(io.Discard, level)
|
||||
return gz
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, setter := range options {
|
||||
setter(handler.Options)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
// Handle is a middleware function for handling gzip compression in HTTP requests and responses.
|
||||
// It first checks if the request has a "Content-Encoding" header set to "gzip" and if a decompression
|
||||
// function is provided, it will call the decompression function. If the handler is set to decompress only,
|
||||
// or if the custom compression decision function indicates not to compress, it will return early.
|
||||
// Otherwise, it retrieves a gzip.Writer from the pool, sets the necessary response headers for gzip encoding,
|
||||
// and wraps the response writer with a gzipWriter. After the request is processed, it ensures the gzip.Writer
|
||||
// is properly closed and the "Content-Length" header is set based on the response size.
|
||||
func (g *gzipHandler) Handle(c *gin.Context) {
|
||||
if fn := g.DecompressFn; fn != nil && c.Request.Header.Get("Content-Encoding") == "gzip" {
|
||||
if fn := g.decompressFn; fn != nil && strings.Contains(c.Request.Header.Get("Content-Encoding"), "gzip") {
|
||||
fn(c)
|
||||
}
|
||||
|
||||
if !g.shouldCompress(c.Request) {
|
||||
if g.decompressOnly ||
|
||||
(g.customShouldCompressFn != nil && !g.customShouldCompressFn(c)) ||
|
||||
(g.customShouldCompressFn == nil && !g.shouldCompress(c.Request)) {
|
||||
return
|
||||
}
|
||||
|
||||
gz := g.gzPool.Get().(*gzip.Writer)
|
||||
defer g.gzPool.Put(gz)
|
||||
defer gz.Reset(io.Discard)
|
||||
gz.Reset(c.Writer)
|
||||
|
||||
c.Header("Content-Encoding", "gzip")
|
||||
c.Header("Vary", "Accept-Encoding")
|
||||
c.Header(headerContentEncoding, "gzip")
|
||||
c.Writer.Header().Add(headerVary, headerAcceptEncoding)
|
||||
// check ETag Header
|
||||
originalEtag := c.GetHeader("ETag")
|
||||
if originalEtag != "" && !strings.HasPrefix(originalEtag, "W/") {
|
||||
c.Header("ETag", "W/"+originalEtag)
|
||||
}
|
||||
c.Writer = &gzipWriter{c.Writer, gz}
|
||||
defer func() {
|
||||
if c.Writer.Size() < 0 {
|
||||
// do not write gzip footer when nothing is written to the response body
|
||||
gz.Reset(io.Discard)
|
||||
}
|
||||
gz.Close()
|
||||
c.Header("Content-Length", fmt.Sprint(c.Writer.Size()))
|
||||
_ = gz.Close()
|
||||
if c.Writer.Size() > -1 {
|
||||
c.Header("Content-Length", strconv.Itoa(c.Writer.Size()))
|
||||
}
|
||||
g.gzPool.Put(gz)
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func (g *gzipHandler) shouldCompress(req *http.Request) bool {
|
||||
if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") ||
|
||||
strings.Contains(req.Header.Get("Connection"), "Upgrade") ||
|
||||
strings.Contains(req.Header.Get("Accept"), "text/event-stream") {
|
||||
if !strings.Contains(req.Header.Get(headerAcceptEncoding), "gzip") ||
|
||||
strings.Contains(req.Header.Get("Connection"), "Upgrade") {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the request path is excluded from compression
|
||||
extension := filepath.Ext(req.URL.Path)
|
||||
if g.ExcludedExtensions.Contains(extension) {
|
||||
return false
|
||||
}
|
||||
|
||||
if g.ExcludedPaths.Contains(req.URL.Path) {
|
||||
return false
|
||||
}
|
||||
if g.ExcludedPathesRegexs.Contains(req.URL.Path) {
|
||||
if g.excludedExtensions.Contains(extension) ||
|
||||
g.excludedPaths.Contains(req.URL.Path) ||
|
||||
g.excludedPathesRegexs.Contains(req.URL.Path) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
208
vendor/github.com/gin-contrib/gzip/options.go
generated
vendored
208
vendor/github.com/gin-contrib/gzip/options.go
generated
vendored
@ -2,6 +2,8 @@ package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@ -10,58 +12,134 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultExcludedExtentions is a predefined list of file extensions that should be excluded from gzip compression.
|
||||
// These extensions typically represent image files that are already compressed
|
||||
// and do not benefit from additional compression.
|
||||
DefaultExcludedExtentions = NewExcludedExtensions([]string{
|
||||
".png", ".gif", ".jpeg", ".jpg",
|
||||
})
|
||||
DefaultOptions = &Options{
|
||||
ExcludedExtensions: DefaultExcludedExtentions,
|
||||
}
|
||||
// ErrUnsupportedContentEncoding is an error that indicates the content encoding
|
||||
// is not supported by the application.
|
||||
ErrUnsupportedContentEncoding = errors.New("unsupported content encoding")
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ExcludedExtensions ExcludedExtensions
|
||||
ExcludedPaths ExcludedPaths
|
||||
ExcludedPathesRegexs ExcludedPathesRegexs
|
||||
DecompressFn func(c *gin.Context)
|
||||
// Option is an interface that defines a method to apply a configuration
|
||||
// to a given config instance. Implementations of this interface can be
|
||||
// used to modify the configuration settings of the logger.
|
||||
type Option interface {
|
||||
apply(*config)
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
// Ensures that optionFunc implements the Option interface at compile time.
|
||||
// If optionFunc does not implement Option, a compile-time error will occur.
|
||||
var _ Option = (*optionFunc)(nil)
|
||||
|
||||
type optionFunc func(*config)
|
||||
|
||||
func (o optionFunc) apply(c *config) {
|
||||
o(c)
|
||||
}
|
||||
|
||||
type config struct {
|
||||
excludedExtensions ExcludedExtensions
|
||||
excludedPaths ExcludedPaths
|
||||
excludedPathesRegexs ExcludedPathesRegexs
|
||||
decompressFn func(c *gin.Context)
|
||||
decompressOnly bool
|
||||
customShouldCompressFn func(c *gin.Context) bool
|
||||
}
|
||||
|
||||
// WithExcludedExtensions returns an Option that sets the ExcludedExtensions field of the Options struct.
|
||||
// Parameters:
|
||||
// - args: []string - A slice of file extensions to exclude from gzip compression.
|
||||
func WithExcludedExtensions(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedExtensions = NewExcludedExtensions(args)
|
||||
}
|
||||
return optionFunc(func(o *config) {
|
||||
o.excludedExtensions = NewExcludedExtensions(args)
|
||||
})
|
||||
}
|
||||
|
||||
// WithExcludedPaths returns an Option that sets the ExcludedPaths field of the Options struct.
|
||||
// Parameters:
|
||||
// - args: []string - A slice of paths to exclude from gzip compression.
|
||||
func WithExcludedPaths(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedPaths = NewExcludedPaths(args)
|
||||
}
|
||||
return optionFunc(func(o *config) {
|
||||
o.excludedPaths = NewExcludedPaths(args)
|
||||
})
|
||||
}
|
||||
|
||||
// WithExcludedPathsRegexs returns an Option that sets the ExcludedPathesRegexs field of the Options struct.
|
||||
// Parameters:
|
||||
// - args: []string - A slice of regex patterns to exclude paths from gzip compression.
|
||||
func WithExcludedPathsRegexs(args []string) Option {
|
||||
return func(o *Options) {
|
||||
o.ExcludedPathesRegexs = NewExcludedPathesRegexs(args)
|
||||
}
|
||||
return optionFunc(func(o *config) {
|
||||
o.excludedPathesRegexs = NewExcludedPathesRegexs(args)
|
||||
})
|
||||
}
|
||||
|
||||
// WithDecompressFn returns an Option that sets the DecompressFn field of the Options struct.
|
||||
// Parameters:
|
||||
// - decompressFn: func(c *gin.Context) - A function to handle decompression of incoming requests.
|
||||
func WithDecompressFn(decompressFn func(c *gin.Context)) Option {
|
||||
return func(o *Options) {
|
||||
o.DecompressFn = decompressFn
|
||||
}
|
||||
return optionFunc(func(o *config) {
|
||||
o.decompressFn = decompressFn
|
||||
})
|
||||
}
|
||||
|
||||
// WithDecompressOnly is an option that configures the gzip middleware to only
|
||||
// decompress incoming requests without compressing the responses. When this
|
||||
// option is enabled, the middleware will set the DecompressOnly field of the
|
||||
// Options struct to true.
|
||||
func WithDecompressOnly() Option {
|
||||
return optionFunc(func(o *config) {
|
||||
o.decompressOnly = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithCustomShouldCompressFn returns an Option that sets the CustomShouldCompressFn field of the Options struct.
|
||||
// Parameters:
|
||||
// - fn: func(c *gin.Context) bool - A function to determine if a request should be compressed.
|
||||
// The function should return true if the request should be compressed, false otherwise.
|
||||
// If the function returns false, the middleware will not compress the response.
|
||||
// If the function is nil, the middleware will use the default logic to determine
|
||||
// if the response should be compressed.
|
||||
//
|
||||
// Returns:
|
||||
// - Option - An option that sets the CustomShouldCompressFn field of the Options struct.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// router.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithCustomShouldCompressFn(func(c *gin.Context) bool {
|
||||
// return c.Request.URL.Path != "/no-compress"
|
||||
// })))
|
||||
func WithCustomShouldCompressFn(fn func(c *gin.Context) bool) Option {
|
||||
return optionFunc(func(o *config) {
|
||||
o.customShouldCompressFn = fn
|
||||
})
|
||||
}
|
||||
|
||||
// Using map for better lookup performance
|
||||
type ExcludedExtensions map[string]struct{}
|
||||
|
||||
// NewExcludedExtensions creates a new ExcludedExtensions map from a slice of file extensions.
|
||||
// Parameters:
|
||||
// - extensions: []string - A slice of file extensions to exclude from gzip compression.
|
||||
//
|
||||
// Returns:
|
||||
// - ExcludedExtensions - A map of excluded file extensions.
|
||||
func NewExcludedExtensions(extensions []string) ExcludedExtensions {
|
||||
res := make(ExcludedExtensions)
|
||||
res := make(ExcludedExtensions, len(extensions))
|
||||
for _, e := range extensions {
|
||||
res[e] = struct{}{}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Contains checks if a given file extension is in the ExcludedExtensions map.
|
||||
// Parameters:
|
||||
// - target: string - The file extension to check.
|
||||
//
|
||||
// Returns:
|
||||
// - bool - True if the extension is excluded, false otherwise.
|
||||
func (e ExcludedExtensions) Contains(target string) bool {
|
||||
_, ok := e[target]
|
||||
return ok
|
||||
@ -69,10 +147,22 @@ func (e ExcludedExtensions) Contains(target string) bool {
|
||||
|
||||
type ExcludedPaths []string
|
||||
|
||||
// NewExcludedPaths creates a new ExcludedPaths slice from a slice of paths.
|
||||
// Parameters:
|
||||
// - paths: []string - A slice of paths to exclude from gzip compression.
|
||||
//
|
||||
// Returns:
|
||||
// - ExcludedPaths - A slice of excluded paths.
|
||||
func NewExcludedPaths(paths []string) ExcludedPaths {
|
||||
return ExcludedPaths(paths)
|
||||
}
|
||||
|
||||
// Contains checks if a given request URI starts with any of the excluded paths.
|
||||
// Parameters:
|
||||
// - requestURI: string - The request URI to check.
|
||||
//
|
||||
// Returns:
|
||||
// - bool - True if the URI starts with an excluded path, false otherwise.
|
||||
func (e ExcludedPaths) Contains(requestURI string) bool {
|
||||
for _, path := range e {
|
||||
if strings.HasPrefix(requestURI, path) {
|
||||
@ -84,14 +174,26 @@ func (e ExcludedPaths) Contains(requestURI string) bool {
|
||||
|
||||
type ExcludedPathesRegexs []*regexp.Regexp
|
||||
|
||||
// NewExcludedPathesRegexs creates a new ExcludedPathesRegexs slice from a slice of regex patterns.
|
||||
// Parameters:
|
||||
// - regexs: []string - A slice of regex patterns to exclude paths from gzip compression.
|
||||
//
|
||||
// Returns:
|
||||
// - ExcludedPathesRegexs - A slice of excluded path regex patterns.
|
||||
func NewExcludedPathesRegexs(regexs []string) ExcludedPathesRegexs {
|
||||
result := make([]*regexp.Regexp, len(regexs))
|
||||
result := make(ExcludedPathesRegexs, len(regexs))
|
||||
for i, reg := range regexs {
|
||||
result[i] = regexp.MustCompile(reg)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Contains checks if a given request URI matches any of the excluded path regex patterns.
|
||||
// Parameters:
|
||||
// - requestURI: string - The request URI to check.
|
||||
//
|
||||
// Returns:
|
||||
// - bool - True if the URI matches an excluded path regex pattern, false otherwise.
|
||||
func (e ExcludedPathesRegexs) Contains(requestURI string) bool {
|
||||
for _, reg := range e {
|
||||
if reg.MatchString(requestURI) {
|
||||
@ -101,16 +203,68 @@ func (e ExcludedPathesRegexs) Contains(requestURI string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultDecompressHandle is a middleware function for the Gin framework that
|
||||
// decompresses the request body if it is gzip encoded. It checks if the request
|
||||
// body is nil and returns immediately if it is. Otherwise, it attempts to create
|
||||
// a new gzip reader from the request body. If an error occurs during this process,
|
||||
// it aborts the request with a 400 Bad Request status and the error. If successful,
|
||||
// it removes the "Content-Encoding" and "Content-Length" headers from the request
|
||||
// and replaces the request body with the decompressed reader.
|
||||
//
|
||||
// Parameters:
|
||||
// - c: *gin.Context - The Gin context for the current request.
|
||||
func DefaultDecompressHandle(c *gin.Context) {
|
||||
if c.Request.Body == nil {
|
||||
return
|
||||
}
|
||||
r, err := gzip.NewReader(c.Request.Body)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusBadRequest, err)
|
||||
|
||||
contentEncodingField := strings.Split(strings.ToLower(c.GetHeader("Content-Encoding")), ",")
|
||||
if len(contentEncodingField) == 0 { // nothing to decompress
|
||||
c.Next()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
toClose := make([]io.Closer, 0, len(contentEncodingField))
|
||||
defer func() {
|
||||
for i := len(toClose); i > 0; i-- {
|
||||
toClose[i-1].Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// parses multiply gzips like
|
||||
// Content-Encoding: gzip, gzip, gzip
|
||||
// allowed by RFC
|
||||
for i := 0; i < len(contentEncodingField); i++ {
|
||||
trimmedValue := strings.TrimSpace(contentEncodingField[i])
|
||||
|
||||
if trimmedValue == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if trimmedValue != "gzip" {
|
||||
// According to RFC 7231, Section 3.1.2.2:
|
||||
// https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.2
|
||||
// An origin server MAY respond with a status code of 415 (Unsupported
|
||||
// Media Type) if a representation in the request message has a content
|
||||
// coding that is not acceptable.
|
||||
_ = c.AbortWithError(http.StatusUnsupportedMediaType, ErrUnsupportedContentEncoding)
|
||||
}
|
||||
|
||||
r, err := gzip.NewReader(c.Request.Body)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusBadRequest, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
toClose = append(toClose, c.Request.Body)
|
||||
|
||||
c.Request.Body = r
|
||||
}
|
||||
|
||||
c.Request.Header.Del("Content-Encoding")
|
||||
c.Request.Header.Del("Content-Length")
|
||||
c.Request.Body = r
|
||||
|
||||
c.Next()
|
||||
}
|
||||
|
3
vendor/github.com/gin-contrib/sse/.golangci.yml
generated
vendored
Normal file
3
vendor/github.com/gin-contrib/sse/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
linters:
|
||||
disable:
|
||||
- errcheck
|
29
vendor/github.com/gin-contrib/sse/.goreleaser.yaml
generated
vendored
Normal file
29
vendor/github.com/gin-contrib/sse/.goreleaser.yaml
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
builds:
|
||||
- # If true, skip the build.
|
||||
# Useful for library projects.
|
||||
# Default is false
|
||||
skip: true
|
||||
|
||||
changelog:
|
||||
use: github
|
||||
groups:
|
||||
- title: Features
|
||||
regexp: "^.*feat[(\\w)]*:+.*$"
|
||||
order: 0
|
||||
- title: "Bug fixes"
|
||||
regexp: "^.*fix[(\\w)]*:+.*$"
|
||||
order: 1
|
||||
- title: "Enhancements"
|
||||
regexp: "^.*chore[(\\w)]*:+.*$"
|
||||
order: 2
|
||||
- title: "Refactor"
|
||||
regexp: "^.*refactor[(\\w)]*:+.*$"
|
||||
order: 3
|
||||
- title: "Build process updates"
|
||||
regexp: ^.*?(build|ci)(\(.+\))??!?:.+$
|
||||
order: 4
|
||||
- title: "Documentation updates"
|
||||
regexp: ^.*?docs?(\(.+\))??!?:.+$
|
||||
order: 4
|
||||
- title: Others
|
||||
order: 999
|
26
vendor/github.com/gin-contrib/sse/.travis.yml
generated
vendored
26
vendor/github.com/gin-contrib/sse/.travis.yml
generated
vendored
@ -1,26 +0,0 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- master
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- go: 1.11.x
|
||||
env: GO111MODULE=on
|
||||
- go: 1.12.x
|
||||
env: GO111MODULE=on
|
||||
|
||||
script:
|
||||
- go test -v -covermode=count -coverprofile=coverage.out
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
42
vendor/github.com/gin-contrib/sse/README.md
generated
vendored
42
vendor/github.com/gin-contrib/sse/README.md
generated
vendored
@ -1,7 +1,7 @@
|
||||
# Server-Sent Events
|
||||
|
||||
[](https://godoc.org/github.com/gin-contrib/sse)
|
||||
[](https://travis-ci.org/gin-contrib/sse)
|
||||
[](https://pkg.go.dev/github.com/gin-contrib/sse)
|
||||
[](https://github.com/gin-contrib/sse/actions/workflows/go.yml)
|
||||
[](https://codecov.io/gh/gin-contrib/sse)
|
||||
[](https://goreportcard.com/report/github.com/gin-contrib/sse)
|
||||
|
||||
@ -16,32 +16,33 @@ Server-sent events (SSE) is a technology where a browser receives automatic upda
|
||||
import "github.com/gin-contrib/sse"
|
||||
|
||||
func httpHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// data can be a primitive like a string, an integer or a float
|
||||
sse.Encode(w, sse.Event{
|
||||
Event: "message",
|
||||
Data: "some data\nmore data",
|
||||
})
|
||||
// data can be a primitive like a string, an integer or a float
|
||||
sse.Encode(w, sse.Event{
|
||||
Event: "message",
|
||||
Data: "some data\nmore data",
|
||||
})
|
||||
|
||||
// also a complex type, like a map, a struct or a slice
|
||||
sse.Encode(w, sse.Event{
|
||||
Id: "124",
|
||||
Event: "message",
|
||||
Data: map[string]interface{}{
|
||||
"user": "manu",
|
||||
"date": time.Now().Unix(),
|
||||
"content": "hi!",
|
||||
},
|
||||
})
|
||||
// also a complex type, like a map, a struct or a slice
|
||||
sse.Encode(w, sse.Event{
|
||||
Id: "124",
|
||||
Event: "message",
|
||||
Data: map[string]interface{}{
|
||||
"user": "manu",
|
||||
"date": time.Now().Unix(),
|
||||
"content": "hi!",
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
```sh
|
||||
event: message
|
||||
data: some data\\nmore data
|
||||
|
||||
id: 124
|
||||
event: message
|
||||
data: {"content":"hi!","date":1431540810,"user":"manu"}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Content-Type
|
||||
@ -49,7 +50,8 @@ data: {"content":"hi!","date":1431540810,"user":"manu"}
|
||||
```go
|
||||
fmt.Println(sse.ContentType)
|
||||
```
|
||||
```
|
||||
|
||||
```sh
|
||||
text/event-stream
|
||||
```
|
||||
|
||||
|
10
vendor/github.com/gin-contrib/sse/sse-encoder.go
generated
vendored
10
vendor/github.com/gin-contrib/sse/sse-encoder.go
generated
vendored
@ -18,7 +18,7 @@ import (
|
||||
// W3C Working Draft 29 October 2009
|
||||
// http://www.w3.org/TR/2009/WD-eventsource-20091029/
|
||||
|
||||
const ContentType = "text/event-stream"
|
||||
const ContentType = "text/event-stream;charset=utf-8"
|
||||
|
||||
var contentType = []string{ContentType}
|
||||
var noCache = []string{"no-cache"}
|
||||
@ -72,6 +72,14 @@ func writeRetry(w stringWriter, retry uint) {
|
||||
|
||||
func writeData(w stringWriter, data interface{}) error {
|
||||
w.WriteString("data:")
|
||||
|
||||
bData, ok := data.([]byte)
|
||||
if ok {
|
||||
dataReplacer.WriteString(w, string(bData))
|
||||
w.WriteString("\n\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch kindOfData(data) {
|
||||
case reflect.Struct, reflect.Slice, reflect.Map:
|
||||
err := json.NewEncoder(w).Encode(data)
|
||||
|
Reference in New Issue
Block a user