mirror of
https://github.com/kataras/iris.git
synced 2026-05-14 18:13:49 +00:00
add Context.ResponseWriter.IsHijacked to report whether the underline conn is already hijacked and a lot of cleanup and minor ws stress test example improvements
Former-commit-id: 444d4f0718d5c6d7544834c5e44dafb872980238
This commit is contained in:
@@ -134,7 +134,7 @@ func main() {
|
||||
|
||||
```
|
||||
|
||||
## Built'n Configurators
|
||||
## Builtin Configurators
|
||||
|
||||
```go
|
||||
// WithoutServerError will cause to ignore the matched "errors"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Logger().SetLevel("debug")
|
||||
// Optionally, add two built'n handlers
|
||||
// Optionally, add two builtin handlers
|
||||
// that can recover from any http-relative panics
|
||||
// and log the requests to the terminal.
|
||||
app.Use(recover.New())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# hero: basic
|
||||
|
||||
## 1. Path Parameters - Built'n Dependencies
|
||||
## 1. Path Parameters - Builtin Dependencies
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ var helloView = hero.View{
|
||||
// Hello will return a predefined view with bind data.
|
||||
//
|
||||
// `hero.Result` is just an interface with a `Dispatch` function.
|
||||
// `hero.Response` and `hero.View` are the built'n result type dispatchers
|
||||
// `hero.Response` and `hero.View` are the builtin result type dispatchers
|
||||
// you can even create custom response dispatchers by
|
||||
// implementing the `github.com/kataras/iris/hero#Result` interface.
|
||||
func Hello() hero.Result {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
// for the main_test.go.
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
// Optionally, add two built'n handlers
|
||||
// Optionally, add two builtin handlers
|
||||
// that can recover from any http-relative panics
|
||||
// and log the requests to the terminal.
|
||||
app.Use(recover.New())
|
||||
|
||||
@@ -23,7 +23,7 @@ var helloView = mvc.View{
|
||||
// Get will return a predefined view with bind data.
|
||||
//
|
||||
// `mvc.Result` is just an interface with a `Dispatch` function.
|
||||
// `mvc.Response` and `mvc.View` are the built'n result type dispatchers
|
||||
// `mvc.Response` and `mvc.View` are the builtin result type dispatchers
|
||||
// you can even create custom response dispatchers by
|
||||
// implementing the `github.com/kataras/iris/hero#Result` interface.
|
||||
func (c *HelloController) Get() mvc.Result {
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
|
||||
/*
|
||||
http://localhost:8080/test_slice_hero/myvaluei1/myavlue2 ->
|
||||
myparam's value (a trailing path parameter type) is: []string{"myvaluei1", "myavlue2"}
|
||||
myparam's value (a trailing path parameter type) is: []string{"myvalue1", "myavlue2"}
|
||||
*/
|
||||
app.Get("/test_slice_hero/{myparam:slice}", hero.Handler(func(myparam []string) string {
|
||||
return fmt.Sprintf("myparam's value (a trailing path parameter type) is: %#v\n", myparam)
|
||||
@@ -66,7 +66,7 @@ func main() {
|
||||
myparam's value (a trailing path parameter type) is: []string{"value1", "value2"}
|
||||
*/
|
||||
app.Get("/test_slice_contains/{myparam:slice contains([value1,value2])}", func(ctx context.Context) {
|
||||
// When it is not a built'n function available to retrieve your value with the type you want, such as ctx.Params().GetInt
|
||||
// When it is not a builtin function available to retrieve your value with the type you want, such as ctx.Params().GetInt
|
||||
// then you can use the `GetEntry.ValueRaw` to get the real value, which is set-ed by your macro above.
|
||||
myparam := ctx.Params().GetEntry("myparam").ValueRaw.([]string)
|
||||
ctx.Writef("myparam's value (a trailing path parameter type) is: %#v\n", myparam)
|
||||
|
||||
@@ -115,7 +115,7 @@ func main() {
|
||||
// see the inline javascript code in the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/echo", ws.Handler())
|
||||
|
||||
// serve the javascript built'n client-side library,
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(websocket.ClientSource)
|
||||
|
||||
@@ -40,7 +40,7 @@ func setupWebsocket(app *iris.Application) {
|
||||
// see the inline javascript code in the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/echo", ws.Handler())
|
||||
|
||||
// serve the javascript built'n client-side library,
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(ws.ClientSource)
|
||||
|
||||
@@ -25,7 +25,7 @@ func main() {
|
||||
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/my_endpoint", ws.Handler())
|
||||
|
||||
// serve the javascript built'n client-side library,
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(websocket.ClientSource)
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -19,7 +20,7 @@ var (
|
||||
)
|
||||
|
||||
const totalClients = 16000 // max depends on the OS.
|
||||
const verbose = true
|
||||
const verbose = false
|
||||
|
||||
var connectionFailures uint64
|
||||
|
||||
@@ -43,7 +44,7 @@ func collectError(op string, err error) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.Println("--Running...")
|
||||
log.Println("-- Running...")
|
||||
var err error
|
||||
f, err = os.Open("./test.data")
|
||||
if err != nil {
|
||||
@@ -63,7 +64,7 @@ func main() {
|
||||
wg.Add(1)
|
||||
waitTime := time.Duration(rand.Intn(5)) * time.Millisecond
|
||||
time.Sleep(waitTime)
|
||||
go connect(wg, 7*time.Second+waitTime)
|
||||
go connect(wg, 14*time.Second+waitTime)
|
||||
}
|
||||
|
||||
for i := 0; i < totalClients/4; i++ {
|
||||
@@ -77,7 +78,7 @@ func main() {
|
||||
wg.Add(1)
|
||||
waitTime := time.Duration(rand.Intn(5)) * time.Millisecond
|
||||
time.Sleep(waitTime)
|
||||
go connect(wg, 14*time.Second+waitTime)
|
||||
go connect(wg, 7*time.Second+waitTime)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@@ -136,16 +137,19 @@ func main() {
|
||||
log.Println("ALL OK.")
|
||||
}
|
||||
|
||||
log.Println("--Finished.")
|
||||
log.Println("-- Finished.")
|
||||
}
|
||||
|
||||
func connect(wg *sync.WaitGroup, alive time.Duration) {
|
||||
c, err := websocket.Dial(nil, url, websocket.ConnectionConfig{})
|
||||
func connect(wg *sync.WaitGroup, alive time.Duration) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), alive)
|
||||
defer cancel()
|
||||
|
||||
c, err := websocket.Dial(ctx, url, websocket.ConnectionConfig{})
|
||||
if err != nil {
|
||||
atomic.AddUint64(&connectionFailures, 1)
|
||||
collectError("connect", err)
|
||||
wg.Done()
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
c.OnError(func(err error) {
|
||||
@@ -167,23 +171,28 @@ func connect(wg *sync.WaitGroup, alive time.Duration) {
|
||||
}
|
||||
})
|
||||
|
||||
go func() {
|
||||
time.Sleep(alive)
|
||||
if err := c.Disconnect(); err != nil {
|
||||
collectError("disconnect", err)
|
||||
}
|
||||
if alive > 0 {
|
||||
go func() {
|
||||
time.Sleep(alive)
|
||||
if err := c.Disconnect(); err != nil {
|
||||
collectError("disconnect", err)
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for !disconnected {
|
||||
if !scanner.Scan() || scanner.Err() != nil {
|
||||
break
|
||||
if !scanner.Scan() {
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
if text := scanner.Text(); len(text) > 1 {
|
||||
c.Emit("chat", text)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,21 +11,24 @@ import (
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
const totalClients = 16000 // max depends on the OS.
|
||||
const verbose = true
|
||||
const (
|
||||
endpoint = "localhost:8080"
|
||||
totalClients = 16000 // max depends on the OS.
|
||||
verbose = false
|
||||
maxC = 0
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
ws := websocket.New(websocket.Config{})
|
||||
ws.OnConnection(handleConnection)
|
||||
|
||||
// websocket.Config{PingPeriod: ((60 * time.Second) * 9) / 10}
|
||||
|
||||
go func() {
|
||||
dur := 8 * time.Second
|
||||
dur := 4 * time.Second
|
||||
if totalClients >= 64000 {
|
||||
// if more than 64000 then let's no check every 8 seconds, let's do it every 24 seconds,
|
||||
// just for simplicity, either way works.
|
||||
// if more than 64000 then let's perform those checks every 24 seconds instead,
|
||||
// either way works.
|
||||
dur = 24 * time.Second
|
||||
}
|
||||
t := time.NewTicker(dur)
|
||||
@@ -40,12 +43,16 @@ func main() {
|
||||
n := ws.GetTotalConnections()
|
||||
if n > 0 {
|
||||
started = true
|
||||
if maxC > 0 && n > maxC {
|
||||
log.Printf("current connections[%d] > MaxConcurrentConnections[%d]", n, maxC)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if started {
|
||||
totalConnected := atomic.LoadUint64(&count)
|
||||
|
||||
if totalConnected == totalClients {
|
||||
disconnectedN := atomic.LoadUint64(&totalDisconnected)
|
||||
connectedN := atomic.LoadUint64(&totalConnected)
|
||||
if disconnectedN == totalClients && connectedN == totalClients {
|
||||
if n != 0 {
|
||||
log.Println("ALL CLIENTS DISCONNECTED BUT LEFTOVERS ON CONNECTIONS LIST.")
|
||||
} else {
|
||||
@@ -53,7 +60,7 @@ func main() {
|
||||
}
|
||||
return
|
||||
} else if n == 0 {
|
||||
log.Printf("%d/%d CLIENTS WERE NOT CONNECTED AT ALL. CHECK YOUR OS NET SETTINGS. ALL OTHER CONNECTED CLIENTS DISCONNECTED SUCCESSFULLY.\n",
|
||||
log.Printf("%d/%d CLIENTS WERE NOT CONNECTED AT ALL. CHECK YOUR OS NET SETTINGS. THE REST CLIENTS WERE DISCONNECTED SUCCESSFULLY.\n",
|
||||
totalClients-totalConnected, totalClients)
|
||||
|
||||
return
|
||||
@@ -64,11 +71,18 @@ func main() {
|
||||
|
||||
app := iris.New()
|
||||
app.Get("/", ws.Handler())
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
app.Run(iris.Addr(endpoint), iris.WithoutServerError(iris.ErrServerClosed))
|
||||
}
|
||||
|
||||
var totalConnected uint64
|
||||
|
||||
func handleConnection(c websocket.Connection) {
|
||||
if c.Err() != nil {
|
||||
log.Fatalf("[%d] upgrade failed: %v", atomic.LoadUint64(&totalConnected)+1, c.Err())
|
||||
return
|
||||
}
|
||||
|
||||
atomic.AddUint64(&totalConnected, 1)
|
||||
c.OnError(func(err error) { handleErr(c, err) })
|
||||
c.OnDisconnect(func() { handleDisconnect(c) })
|
||||
c.On("chat", func(message string) {
|
||||
@@ -76,12 +90,12 @@ func handleConnection(c websocket.Connection) {
|
||||
})
|
||||
}
|
||||
|
||||
var count uint64
|
||||
var totalDisconnected uint64
|
||||
|
||||
func handleDisconnect(c websocket.Connection) {
|
||||
atomic.AddUint64(&count, 1)
|
||||
newC := atomic.AddUint64(&totalDisconnected, 1)
|
||||
if verbose {
|
||||
log.Printf("client [%s] disconnected!\n", c.ID())
|
||||
log.Printf("[%d] client [%s] disconnected!\n", newC, c.ID())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func main() {
|
||||
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/my_endpoint", ws.Handler())
|
||||
|
||||
// serve the javascript built'n client-side library,
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(websocket.ClientSource)
|
||||
|
||||
Reference in New Issue
Block a user