2023-03-06 17:35:39 +03:00
//nolint:wrapcheck // We must not wrap errors in tests
2022-08-01 09:24:37 +03:00
package fiber
import (
2022-08-01 12:16:49 +02:00
"bytes"
2022-09-08 08:57:05 +03:00
"context"
2022-08-01 09:24:37 +03:00
"crypto/tls"
2022-09-08 08:57:05 +03:00
"errors"
2022-08-01 09:24:37 +03:00
"fmt"
2022-08-01 12:16:49 +02:00
"io"
2024-03-17 13:46:20 +01:00
"log" //nolint:depguard // TODO: Required to capture output, use internal log package instead
2022-09-08 08:57:05 +03:00
"net"
2022-08-01 12:16:49 +02:00
"os"
2022-08-01 09:24:37 +03:00
"strings"
2022-08-01 12:16:49 +02:00
"sync"
2022-08-01 09:24:37 +03:00
"testing"
"time"
2024-03-08 14:03:13 -05:00
"github.com/stretchr/testify/assert"
2022-08-22 13:57:10 +08:00
"github.com/stretchr/testify/require"
2024-03-04 15:49:14 +08:00
"github.com/valyala/fasthttp"
2022-08-01 09:24:37 +03:00
"github.com/valyala/fasthttp/fasthttputil"
)
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen
func Test_Listen ( t * testing . T ) {
app := New ( )
2022-08-01 09:24:37 +03:00
2024-01-21 23:34:15 -08:00
require . Error ( t , app . Listen ( ":99999" ) )
2022-08-01 09:24:37 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 09:24:37 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":4003" , ListenConfig { DisableStartupMessage : true } ) )
2022-09-08 08:57:05 +03:00
}
// go test -run Test_Listen_Graceful_Shutdown
func Test_Listen_Graceful_Shutdown ( t * testing . T ) {
var mu sync . Mutex
var shutdown bool
app := New ( )
app . Get ( "/" , func ( c Ctx ) error {
return c . SendString ( c . Hostname ( ) )
} )
ln := fasthttputil . NewInmemoryListener ( )
2024-03-08 14:03:13 -05:00
errs := make ( chan error )
2022-09-08 08:57:05 +03:00
go func ( ) {
2024-03-08 14:03:13 -05:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 2 * time . Second )
2022-09-08 08:57:05 +03:00
defer cancel ( )
2024-03-08 14:03:13 -05:00
errs <- app . Listener ( ln , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
GracefulContext : ctx ,
OnShutdownSuccess : func ( ) {
mu . Lock ( )
shutdown = true
mu . Unlock ( )
} ,
} )
} ( )
2024-03-08 14:03:13 -05:00
// Server readiness check
for i := 0 ; i < 10 ; i ++ {
conn , err := ln . Dial ( )
if err == nil {
conn . Close ( ) //nolint:errcheck // ignore error
break
}
// Wait a bit before retrying
time . Sleep ( 100 * time . Millisecond )
if i == 9 {
t . Fatalf ( "Server did not become ready in time: %v" , err )
}
}
2022-09-08 08:57:05 +03:00
testCases := [ ] struct {
Time time . Duration
ExpectedBody string
ExpectedStatusCode int
2024-03-04 15:49:14 +08:00
ExpectedErr error
2022-09-08 08:57:05 +03:00
} {
2024-03-08 14:03:13 -05:00
{ Time : 500 * time . Millisecond , ExpectedBody : "example.com" , ExpectedStatusCode : StatusOK , ExpectedErr : nil } ,
{ Time : 3 * time . Second , ExpectedBody : "" , ExpectedStatusCode : StatusOK , ExpectedErr : errors . New ( "InmemoryListener is already closed: use of closed network connection" ) } ,
2022-09-08 08:57:05 +03:00
}
for _ , tc := range testCases {
time . Sleep ( tc . Time )
2024-03-04 15:49:14 +08:00
req := fasthttp . AcquireRequest ( )
req . SetRequestURI ( "http://example.com" )
2022-09-08 08:57:05 +03:00
2024-03-04 15:49:14 +08:00
client := fasthttp . HostClient { }
client . Dial = func ( _ string ) ( net . Conn , error ) { return ln . Dial ( ) }
resp := fasthttp . AcquireResponse ( )
err := client . Do ( req , resp )
require . Equal ( t , tc . ExpectedErr , err )
require . Equal ( t , tc . ExpectedStatusCode , resp . StatusCode ( ) )
require . Equal ( t , tc . ExpectedBody , string ( resp . Body ( ) ) )
fasthttp . ReleaseRequest ( req )
fasthttp . ReleaseResponse ( resp )
2022-09-08 08:57:05 +03:00
}
mu . Lock ( )
2024-03-08 14:03:13 -05:00
err := <- errs
2022-09-08 08:57:05 +03:00
require . True ( t , shutdown )
2024-03-08 14:03:13 -05:00
require . NoError ( t , err )
2022-09-08 08:57:05 +03:00
mu . Unlock ( )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_Prefork
func Test_Listen_Prefork ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
testPreforkMaster = true
2022-09-08 08:57:05 +03:00
app := New ( )
2022-08-01 09:24:37 +03:00
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":99999" , ListenConfig { DisableStartupMessage : true , EnablePrefork : true } ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_TLS
func Test_Listen_TLS ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
app := New ( )
// invalid port
2024-01-21 23:34:15 -08:00
require . Error ( t , app . Listen ( ":99999" , ListenConfig {
2022-09-08 08:57:05 +03:00
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
2024-01-21 23:34:15 -08:00
} ) )
2022-08-01 09:24:37 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 09:24:37 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
} ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_TLS_Prefork
func Test_Listen_TLS_Prefork ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
testPreforkMaster = true
2022-09-08 08:57:05 +03:00
app := New ( )
2022-08-01 09:24:37 +03:00
// invalid key file content
2024-01-21 23:34:15 -08:00
require . Error ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
EnablePrefork : true ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/template.tmpl" ,
2024-01-21 23:34:15 -08:00
} ) )
2022-09-08 08:57:05 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-09-08 08:57:05 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":99999" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
EnablePrefork : true ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
} ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_MutualTLS
func Test_Listen_MutualTLS ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
app := New ( )
// invalid port
2024-01-21 23:34:15 -08:00
require . Error ( t , app . Listen ( ":99999" , ListenConfig {
2022-09-08 08:57:05 +03:00
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
CertClientFile : "./.github/testdata/ca-chain.cert.pem" ,
2024-01-21 23:34:15 -08:00
} ) )
2022-08-01 09:24:37 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 09:24:37 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
CertClientFile : "./.github/testdata/ca-chain.cert.pem" ,
} ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_MutualTLS_Prefork
func Test_Listen_MutualTLS_Prefork ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
testPreforkMaster = true
2022-09-08 08:57:05 +03:00
app := New ( )
2022-08-01 09:24:37 +03:00
// invalid key file content
2024-01-21 23:34:15 -08:00
require . Error ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
EnablePrefork : true ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/template.html" ,
CertClientFile : "./.github/testdata/ca-chain.cert.pem" ,
2024-01-21 23:34:15 -08:00
} ) )
2022-09-08 08:57:05 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-09-08 08:57:05 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":99999" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
EnablePrefork : true ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
CertClientFile : "./.github/testdata/ca-chain.cert.pem" ,
} ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listener
func Test_Listener ( t * testing . T ) {
2022-08-01 09:24:37 +03:00
app := New ( )
go func ( ) {
time . Sleep ( 500 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 09:24:37 +03:00
} ( )
ln := fasthttputil . NewInmemoryListener ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listener ( ln ) )
2022-08-01 09:24:37 +03:00
}
func Test_App_Listener_TLS_Listener ( t * testing . T ) {
// Create tls certificate
cer , err := tls . LoadX509KeyPair ( "./.github/testdata/ssl.pem" , "./.github/testdata/ssl.key" )
if err != nil {
2022-08-22 13:57:10 +08:00
require . NoError ( t , err )
2022-08-01 09:24:37 +03:00
}
2023-01-27 09:01:37 +01:00
//nolint:gosec // We're in a test so using old ciphers is fine
2022-08-01 09:24:37 +03:00
config := & tls . Config { Certificates : [ ] tls . Certificate { cer } }
2023-01-27 09:01:37 +01:00
//nolint:gosec // We're in a test so listening on all interfaces is fine
2022-08-01 09:24:37 +03:00
ln , err := tls . Listen ( NetworkTCP4 , ":0" , config )
2022-08-22 13:57:10 +08:00
require . NoError ( t , err )
2022-08-01 09:24:37 +03:00
app := New ( )
go func ( ) {
time . Sleep ( time . Millisecond * 500 )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 09:24:37 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listener ( ln ) )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_TLSConfigFunc
func Test_Listen_TLSConfigFunc ( t * testing . T ) {
var callTLSConfig bool
app := New ( )
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 12:16:49 +02:00
} ( )
2022-09-08 08:57:05 +03:00
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
2024-02-13 02:23:15 -05:00
TLSConfigFunc : func ( _ * tls . Config ) {
2022-09-08 08:57:05 +03:00
callTLSConfig = true
} ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
} ) )
require . True ( t , callTLSConfig )
}
// go test -run Test_Listen_ListenerAddrFunc
func Test_Listen_ListenerAddrFunc ( t * testing . T ) {
var network string
app := New ( )
2022-08-01 12:16:49 +02:00
go func ( ) {
2022-09-08 08:57:05 +03:00
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-08-01 12:16:49 +02:00
} ( )
2022-09-08 08:57:05 +03:00
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
ListenerAddrFunc : func ( addr net . Addr ) {
network = addr . Network ( )
} ,
CertFile : "./.github/testdata/ssl.pem" ,
CertKeyFile : "./.github/testdata/ssl.key" ,
} ) )
require . Equal ( t , "tcp" , network )
2022-08-01 12:16:49 +02:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_BeforeServeFunc
func Test_Listen_BeforeServeFunc ( t * testing . T ) {
var handlers uint32
app := New ( )
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-09-08 08:57:05 +03:00
} ( )
2024-01-21 23:34:15 -08:00
wantErr := errors . New ( "test" )
require . ErrorIs ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
BeforeServeFunc : func ( fiber * App ) error {
handlers = fiber . HandlersCount ( )
2024-01-21 23:34:15 -08:00
return wantErr
2022-09-08 08:57:05 +03:00
} ,
2024-01-21 23:34:15 -08:00
} ) , wantErr )
2022-09-08 08:57:05 +03:00
2024-01-21 23:34:15 -08:00
require . Zero ( t , handlers )
2022-09-08 08:57:05 +03:00
}
// go test -run Test_Listen_ListenerNetwork
func Test_Listen_ListenerNetwork ( t * testing . T ) {
var network string
app := New ( )
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-09-08 08:57:05 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
ListenerNetwork : NetworkTCP6 ,
ListenerAddrFunc : func ( addr net . Addr ) {
network = addr . String ( )
} ,
} ) )
2024-01-21 23:34:15 -08:00
require . Contains ( t , network , "[::]:" )
2022-09-08 08:57:05 +03:00
go func ( ) {
time . Sleep ( 1000 * time . Millisecond )
2024-03-08 14:03:13 -05:00
assert . NoError ( t , app . Shutdown ( ) )
2022-09-08 08:57:05 +03:00
} ( )
2024-01-21 23:34:15 -08:00
require . NoError ( t , app . Listen ( ":0" , ListenConfig {
2022-09-08 08:57:05 +03:00
DisableStartupMessage : true ,
ListenerNetwork : NetworkTCP4 ,
ListenerAddrFunc : func ( addr net . Addr ) {
network = addr . String ( )
} ,
} ) )
2024-01-21 23:34:15 -08:00
require . Contains ( t , network , "0.0.0.0:" )
2022-09-08 08:57:05 +03:00
}
// go test -run Test_Listen_Master_Process_Show_Startup_Message
func Test_Listen_Master_Process_Show_Startup_Message ( t * testing . T ) {
cfg := ListenConfig {
EnablePrefork : true ,
}
2022-08-01 12:16:49 +02:00
startupMessage := captureOutput ( func ( ) {
2022-09-08 08:57:05 +03:00
New ( ) .
startupMessage ( ":3000" , true , strings . Repeat ( ",11111,22222,33333,44444,55555,60000" , 10 ) , cfg )
2022-08-01 12:16:49 +02:00
} )
2022-09-15 10:53:07 +03:00
colors := Colors { }
2024-01-21 23:34:15 -08:00
require . Contains ( t , startupMessage , "https://127.0.0.1:3000" )
require . Contains ( t , startupMessage , "(bound on host 0.0.0.0 and port 3000)" )
require . Contains ( t , startupMessage , "Child PIDs" )
require . Contains ( t , startupMessage , "11111, 22222, 33333, 44444, 55555, 60000" )
2024-02-10 21:55:04 +01:00
require . Contains ( t , startupMessage , fmt . Sprintf ( "Prefork: \t\t\t%sEnabled%s" , colors . Blue , colors . Reset ) )
2022-08-01 12:16:49 +02:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithAppName
func Test_Listen_Master_Process_Show_Startup_MessageWithAppName ( t * testing . T ) {
cfg := ListenConfig {
EnablePrefork : true ,
}
2022-08-01 12:16:49 +02:00
2022-09-08 08:57:05 +03:00
app := New ( Config { AppName : "Test App v3.0.0" } )
2022-08-01 12:16:49 +02:00
startupMessage := captureOutput ( func ( ) {
2022-09-08 08:57:05 +03:00
app . startupMessage ( ":3000" , true , strings . Repeat ( ",11111,22222,33333,44444,55555,60000" , 10 ) , cfg )
2022-08-01 12:16:49 +02:00
} )
2022-09-08 08:57:05 +03:00
require . Equal ( t , "Test App v3.0.0" , app . Config ( ) . AppName )
2024-01-21 23:34:15 -08:00
require . Contains ( t , startupMessage , app . Config ( ) . AppName )
2022-08-01 12:16:49 +02:00
}
2022-09-15 10:53:07 +03:00
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithAppNameNonAscii
func Test_Listen_Master_Process_Show_Startup_MessageWithAppNameNonAscii ( t * testing . T ) {
cfg := ListenConfig {
EnablePrefork : true ,
}
appName := "Serveur de vérification des données"
app := New ( Config { AppName : appName } )
startupMessage := captureOutput ( func ( ) {
app . startupMessage ( ":3000" , false , "" , cfg )
} )
2024-01-21 23:34:15 -08:00
require . Contains ( t , startupMessage , "Serveur de vérification des données" )
2022-09-15 10:53:07 +03:00
}
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithDisabledPreforkAndCustomEndpoint
func Test_Listen_Master_Process_Show_Startup_MessageWithDisabledPreforkAndCustomEndpoint ( t * testing . T ) {
cfg := ListenConfig {
EnablePrefork : false ,
}
appName := "Fiber Example Application"
app := New ( Config { AppName : appName } )
startupMessage := captureOutput ( func ( ) {
app . startupMessage ( "server.com:8081" , true , strings . Repeat ( ",11111,22222,33333,44444,55555,60000" , 5 ) , cfg )
} )
colors := Colors { }
2024-01-21 23:34:15 -08:00
require . Contains ( t , startupMessage , fmt . Sprintf ( "%sINFO%s" , colors . Green , colors . Reset ) )
require . Contains ( t , startupMessage , fmt . Sprintf ( "%s%s%s" , colors . Blue , appName , colors . Reset ) )
require . Contains ( t , startupMessage , fmt . Sprintf ( "%s%s%s" , colors . Blue , "https://server.com:8081" , colors . Reset ) )
2024-02-10 21:55:04 +01:00
require . Contains ( t , startupMessage , fmt . Sprintf ( "Prefork: \t\t\t%sDisabled%s" , colors . Red , colors . Reset ) )
2022-09-15 10:53:07 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_Print_Route
func Test_Listen_Print_Route ( t * testing . T ) {
app := New ( )
2022-08-01 09:24:37 +03:00
app . Get ( "/" , emptyHandler ) . Name ( "routeName" )
printRoutesMessage := captureOutput ( func ( ) {
app . printRoutesMessage ( )
} )
2024-01-21 23:34:15 -08:00
require . Contains ( t , printRoutesMessage , MethodGet )
require . Contains ( t , printRoutesMessage , "/" )
require . Contains ( t , printRoutesMessage , "emptyHandler" )
require . Contains ( t , printRoutesMessage , "routeName" )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
// go test -run Test_Listen_Print_Route_With_Group
func Test_Listen_Print_Route_With_Group ( t * testing . T ) {
app := New ( )
2022-08-01 09:24:37 +03:00
app . Get ( "/" , emptyHandler )
v1 := app . Group ( "v1" )
v1 . Get ( "/test" , emptyHandler ) . Name ( "v1" )
v1 . Post ( "/test/fiber" , emptyHandler )
v1 . Put ( "/test/fiber/*" , emptyHandler )
printRoutesMessage := captureOutput ( func ( ) {
app . printRoutesMessage ( )
} )
2024-01-21 23:34:15 -08:00
require . Contains ( t , printRoutesMessage , MethodGet )
require . Contains ( t , printRoutesMessage , "/" )
require . Contains ( t , printRoutesMessage , "emptyHandler" )
require . Contains ( t , printRoutesMessage , "/v1/test" )
require . Contains ( t , printRoutesMessage , "POST" )
require . Contains ( t , printRoutesMessage , "/v1/test/fiber" )
require . Contains ( t , printRoutesMessage , "PUT" )
require . Contains ( t , printRoutesMessage , "/v1/test/fiber/*" )
2022-08-01 09:24:37 +03:00
}
2022-09-08 08:57:05 +03:00
func captureOutput ( f func ( ) ) string {
reader , writer , err := os . Pipe ( )
if err != nil {
panic ( err )
}
stdout := os . Stdout
stderr := os . Stderr
defer func ( ) {
os . Stdout = stdout
os . Stderr = stderr
log . SetOutput ( os . Stderr )
} ( )
os . Stdout = writer
os . Stderr = writer
log . SetOutput ( writer )
out := make ( chan string )
wg := new ( sync . WaitGroup )
wg . Add ( 1 )
go func ( ) {
var buf bytes . Buffer
wg . Done ( )
_ , err := io . Copy ( & buf , reader )
if err != nil {
panic ( err )
}
out <- buf . String ( )
} ( )
wg . Wait ( )
f ( )
err = writer . Close ( )
if err != nil {
panic ( err )
}
return <- out
}
2022-09-03 23:56:45 +03:00
func emptyHandler ( _ Ctx ) error {
2022-08-01 09:24:37 +03:00
return nil
}