From 33028f900de2dfccb8b4b5efa5541b2a2d1f3378 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Tue, 25 Jun 2019 22:10:10 +0300 Subject: [PATCH] update the nantive-messages(only) example to the latest websocket (minimum changes, the idea is the same) and misc Former-commit-id: 9598319bc13e8a383114c37f4da84f337ab47b22 --- _benchmarks/benchmarker/benchmarker.go | 59 ++++++++++++++--- _examples/routing/README.md | 48 ++++++++++++-- _examples/websocket/basic/browser/index.html | 2 +- _examples/websocket/native-messages/main.go | 63 +++++++++---------- .../native-messages/static/js/chat.js | 57 ++++++++--------- .../native-messages/templates/client.html | 16 +++-- context/context.go | 6 +- websocket/websocket.go | 9 ++- 8 files changed, 172 insertions(+), 88 deletions(-) diff --git a/_benchmarks/benchmarker/benchmarker.go b/_benchmarks/benchmarker/benchmarker.go index f4f812d3..f43a9087 100644 --- a/_benchmarks/benchmarker/benchmarker.go +++ b/_benchmarks/benchmarker/benchmarker.go @@ -40,6 +40,15 @@ var bundles = []bundle{ installDir: "./platforms/git", installArguments: []string{"-InstallDir", "$installDir"}, }, + { + names: []string{"go"}, // get-only, at least for now. + installDir: "./platforms/go", + installArguments: []string{"-InstallDir", "$installDir"}, + }, + { + names: []string{"bombardier"}, + installDir: "./platforms/bombardier", + }, } func install(b bundle) error { @@ -51,6 +60,8 @@ func install(b bundle) error { return installNode(b) case "git": return installGit(b) + case "bombardier": + return installBombardier(b) } } @@ -91,7 +102,7 @@ type platform struct { func (p *platform) text(args ...string) string { cmd := exec.Command(p.executable, args...) - b, err := cmd.Output() + b, err := cmd.CombinedOutput() if err != nil { logger.Error(err) return "" @@ -111,7 +122,7 @@ func (p *platform) attach(logLevel string, args ...string) error { return cmd.Run() } -func attachCmd(logLevel string, cmd *exec.Cmd) { +func attachCmd(logLevel string, cmd *exec.Cmd) *exec.Cmd { level := golog.ParseLevel(logLevel) outputReader, err := cmd.StdoutPipe() if err == nil { @@ -130,11 +141,21 @@ func attachCmd(logLevel string, cmd *exec.Cmd) { go func() { defer errReader.Close() for errScanner.Scan() { - logger.Log(level, errScanner.Text()) + logger.Log(level, errScanner.Text()) // don't print at error. } }() } } + + return cmd +} + +func resolveFilename(name string) string { + if runtime.GOOS == "windows" { + name += ".exe" + } + + return name } func getPlatform(name string) (p *platform) { @@ -164,10 +185,7 @@ func getPlatform(name string) (p *platform) { logger.Fatalf("unable to auto-install %s, please do it yourself: %v", name, err) } - if runtime.GOOS == "windows" { - name += ".exe" - } - + name = resolveFilename(name) // first check for installDir/bin/+name before the installDir/+name to // find the installed executable (we could return it from our scripts but we don't). binExecutable := b.installDir + "/bin/" + name @@ -206,5 +224,30 @@ func main() { gitVersion := git.text("--version") logger.Info("Git version: ", gitVersion) - os.Stdin.Read(make([]byte, 0)) + golang := getPlatform("go") + goVersion := golang.text("version") + logger.Info("Go version: ", goVersion) + + bombardier := getPlatform("bombardier") + bombardierVersion := bombardier.text("--version") + logger.Info("Bombardier version: ", bombardierVersion) +} + +func installBombardier(b bundle) error { + const ( + repo = "github.com/codesenberg/bombardier" + latestVersion = "1.2.4" + ) + + dst := filepath.Join(os.Getenv("GOPATH"), "/src", repo) + os.RemoveAll(dst) // remove any copy that $GOPATH may have. + + if err := getPlatform("git").exec("clone", "https://"+repo, dst); err != nil { + return err + } + + executable := resolveFilename(b.names[0]) + executableOutput := filepath.Join(b.installDir, executable) + + return getPlatform("go").attach("info", "build", "-ldflags", "-X main.version="+latestVersion, "-o", executableOutput, dst) } diff --git a/_examples/routing/README.md b/_examples/routing/README.md index b776376e..c37b75b2 100644 --- a/_examples/routing/README.md +++ b/_examples/routing/README.md @@ -685,6 +685,25 @@ The `iris.Context` source code can be found [here](https://github.com/kataras/ir // context.Context is very extensible and developers can override // its methods if that is actually needed. type Context interface { + // BeginRequest is executing once for each request + // it should prepare the (new or acquired from pool) context's fields for the new request. + // + // To follow the iris' flow, developer should: + // 1. reset handlers to nil + // 2. reset values to empty + // 3. reset sessions to nil + // 4. reset response writer to the http.ResponseWriter + // 5. reset request to the *http.Request + // and any other optional steps, depends on dev's application type. + BeginRequest(http.ResponseWriter, *http.Request) + // EndRequest is executing once after a response to the request was sent and this context is useless or released. + // + // To follow the iris' flow, developer should: + // 1. flush the response writer's result + // 2. release the response writer + // and any other optional steps, depends on dev's application type. + EndRequest() + // ResponseWriter returns an http.ResponseWriter compatible response writer, as expected. ResponseWriter() ResponseWriter // ResetResponseWriter should change or upgrade the Context's ResponseWriter. @@ -692,6 +711,18 @@ type Context interface { // Request returns the original *http.Request, as expected. Request() *http.Request + // ResetRequest sets the Context's Request, + // It is useful to store the new request created by a std *http.Request#WithContext() into Iris' Context. + // Use `ResetRequest` when for some reason you want to make a full + // override of the *http.Request. + // Note that: when you just want to change one of each fields you can use the Request() which returns a pointer to Request, + // so the changes will have affect without a full override. + // Usage: you use a native http handler which uses the standard "context" package + // to get values instead of the Iris' Context#Values(): + // r := ctx.Request() + // stdCtx := context.WithValue(r.Context(), key, val) + // ctx.ResetRequest(r.WithContext(stdCtx)). + ResetRequest(r *http.Request) // SetCurrentRouteName sets the route's name internally, // in order to be able to find the correct current "read-only" Route when @@ -732,7 +763,7 @@ type Context interface { // HandlerIndex sets the current index of the // current context's handlers chain. // If -1 passed then it just returns the - // current handler index without change the current index.rns that index, useless return value. + // current handler index without change the current index. // // Look Handlers(), Next() and StopExecution() too. HandlerIndex(n int) (currentIndex int) @@ -775,6 +806,12 @@ type Context interface { Proceed(Handler) bool // HandlerName returns the current handler's name, helpful for debugging. HandlerName() string + // HandlerFileLine returns the current running handler's function source file and line information. + // Useful mostly when debugging. + HandlerFileLine() (file string, line int) + // RouteName returns the route name that this handler is running on. + // Note that it will return empty on not found handlers. + RouteName() string // Next calls all the next handler from the handlers chain, // it should be used inside a middleware. // @@ -853,7 +890,8 @@ type Context interface { // that can be used to share information between handlers and middleware. Values() *memstore.Store // Translate is the i18n (localization) middleware's function, - // it calls the Get("translate") to return the translated value. + // it calls the Values().Get(ctx.Application().ConfigurationReadOnly().GetTranslateFunctionContextKey()) + // to execute the translate function and return the localized text value. // // Example: https://github.com/kataras/iris/tree/master/_examples/miscellaneous/i18n Translate(format string, args ...interface{}) string @@ -870,7 +908,6 @@ type Context interface { // RequestPath returns the full request path, // based on the 'escape'. RequestPath(escape bool) string - // Host returns the host part of the current url. Host() string // Subdomain returns the subdomain of this request, if any. @@ -878,6 +915,9 @@ type Context interface { Subdomain() (subdomain string) // IsWWW returns true if the current subdomain (if any) is www. IsWWW() bool + // FullRqeuestURI returns the full URI, + // including the scheme, the host and the relative requested path/resource. + FullRequestURI() string // RemoteAddr tries to parse and return the real client's request IP. // // Based on allowed headers names that can be modified from Configuration.RemoteAddrHeaders. @@ -1189,7 +1229,7 @@ type Context interface { // Note that it has nothing to do with server-side caching. // It does those checks by checking if the "If-Modified-Since" request header // sent by client or a previous server response header - // (e.g with WriteWithExpiration or StaticEmbedded or Favicon etc.) + // (e.g with WriteWithExpiration or HandleDir or Favicon etc.) // is a valid one and it's before the "modtime". // // A check for !modtime && err == nil is necessary to make sure that diff --git a/_examples/websocket/basic/browser/index.html b/_examples/websocket/basic/browser/index.html index b20a90e3..e956b3ae 100644 --- a/_examples/websocket/basic/browser/index.html +++ b/_examples/websocket/basic/browser/index.html @@ -10,7 +10,7 @@ However, `neffos.(min.)js` is a NPM package too so alternatively, you can use it as dependency on your package.json and all nodejs-npm tooling become available: see the "browserify" example for more--> - + - - + \ No newline at end of file diff --git a/context/context.go b/context/context.go index 61944db2..c06fe5ca 100644 --- a/context/context.go +++ b/context/context.go @@ -2602,11 +2602,11 @@ func (ctx *context) ClientSupportsGzip() bool { } var ( - errClientDoesNotSupportGzip = errors.New("client doesn't supports gzip compression") + errClientDoesNotSupportGzip = errors.New("client doesn't support gzip compression") ) // WriteGzip accepts bytes, which are compressed to gzip format and sent to the client. -// returns the number of bytes written and an error ( if the client doesn' supports gzip compression) +// returns the number of bytes written and an error ( if the client doesn't support gzip compression) // // You may re-use this function in the same handler // to write more data many times without any troubles. @@ -2624,7 +2624,7 @@ func (ctx *context) TryWriteGzip(b []byte) (int, error) { n, err := ctx.WriteGzip(b) if err != nil { // check if the error came from gzip not allowed and not the writer itself - if _, ok := err.(*errors.Error); ok { + if _, ok := err.(errors.Error); ok { // client didn't supported gzip, write them uncompressed: return ctx.writer.Write(b) } diff --git a/websocket/websocket.go b/websocket/websocket.go index ad65ca3d..6b14ef7f 100644 --- a/websocket/websocket.go +++ b/websocket/websocket.go @@ -34,7 +34,6 @@ var ( // GobwasDialer is a `Dialer` type for the gobwas/ws subprotocol implementation. // Should be used on `Dial` to create a new client/client-side connection. GobwasDialer = gobwas.Dialer - // DefaultGorillaDialer is a gorilla/websocket dialer with all fields set to the default values. DefaultGorillaDialer = gorilla.DefaultDialer // DefaultGobwasDialer is a gobwas/ws dialer with all fields set to the default values. @@ -50,6 +49,14 @@ var ( // See examples for more. Dial = neffos.Dial + // IsTryingToReconnect reports whether the "err" is from a client + // that was trying to reconnect to the websocket server, + // the first output parameter is the number of total reconnection retries, + // including the previous failures and the succeed last one. + // + // Use it on registered callbacks for `Server#OnUpgradeError`. + IsTryingToReconnect = neffos.IsTryingToReconnect + // OnNamespaceConnect is the event name which its callback is fired right before namespace connect, // if non-nil error then the remote connection's `Conn.Connect` will fail and send that error text. // Connection is not ready to emit data to the namespace.