diff --git a/HISTORY.md b/HISTORY.md index 608ef6e9..2689307b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,29 @@ **How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`. +## 3.0.0-rc.4 -> 3.0.0-pre.release + +- `context.PostFormValue` -> `context.FormValueString`, old func stays until the next revision +- `context.PostFormMulti` -> `context.FormValues` , old func stays until the next revision + +- Added `context.VisitAllCookies(func(key,value string))` to visit all your cookies (because `context.Request.Header.VisitAllCookie` has a bug(I can't fix/pr it because the author is away atm)) +- Added `context.GetFlashes` to get all available flash messages for a particular request +- Fix flash message removed after the first `GetFlash` call in the same request + +**NEW FEATURE**: Built'n support for multi listening servers per iris station, secondary and virtual servers with one-line using the `iris.AddServer` & `iris.Go` to start all servers. + +- `iris.SecondaryListen` -> `iris.AddServer`, old func stays until the next revision +- Added `iris.Servers` with this field you can manage your servers very easy +- Added `iris.AddServer/iris.ListenTo/iris.Go`, but funcs like `Listen/ListenTLS/ListenUNIX` will stay forever +- Added `config.Server.Virtual(bool), config.Server.RedirectTo(string) and config.Server.MaxRequestBodySize(int64)` +- Added `iris.Available (channel bool)` + +**NEW FEATURE**: Build'n support for your API's end-to-end tests + +- Added `tester := iris.Tester(*testing.T)` , look inside: [http_test.go](https://github.com/kataras/iris/blob/master/http_test.go) & [./context_test.go](https://github.com/kataras/iris/blob/master/context_test.go) for `Tester` usage, you can also look inside the [httpexpect's repo](https://github.com/gavv/httpexpect/blob/master/example/iris_test.go) for extended examples with Iris. + + + ## 3.0.0-rc.3 -> 3.0.0-rc.4 **NEW FEATURE**: **Handlebars** template engine support with all Iris' view engine's functions/helpers support, as requested [here](https://github.com/kataras/iris/issues/239): diff --git a/README.md b/README.md index cff7b320..01ebcd90 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ I recommend writing your API tests using this new library, [httpexpect](https:// Versioning ------------ -Current: **v3.0.0-rc.4** +Current: **v3.0.0-pre.release** > Iris is an active project @@ -185,7 +185,7 @@ License can be found [here](LICENSE). [Travis]: http://travis-ci.org/kataras/iris [License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square [License]: https://github.com/kataras/iris/blob/master/LICENSE -[Release Widget]: https://img.shields.io/badge/release-v3.0.0--rc.4-blue.svg?style=flat-square +[Release Widget]: https://img.shields.io/badge/release-v3.0.0--pre.release-blue.svg?style=flat-square [Release]: https://github.com/kataras/iris/releases [Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square [Chat]: https://kataras.rocket.chat/channel/iris diff --git a/context.go b/context.go index b1fadd50..1136c1c6 100644 --- a/context.go +++ b/context.go @@ -286,18 +286,13 @@ func (ctx *Context) RequestHeader(k string) string { return utils.BytesToString(ctx.RequestCtx.Request.Header.Peek(k)) } -// PostFormValue returns a single value from post request's data -func (ctx *Context) PostFormValue(name string) string { - return ctx.FormValueString(name) -} - // FormValueString returns a single value, as string, from post request's data func (ctx *Context) FormValueString(name string) string { return string(ctx.FormValue(name)) } -// PostFormMulti returns a slice of string from post request's data -func (ctx *Context) PostFormMulti(name string) []string { +// FormValues returns a slice of string from post request's data +func (ctx *Context) FormValues(name string) []string { arrBytes := ctx.PostArgs().PeekMulti(name) arrStr := make([]string, len(arrBytes)) for i, v := range arrBytes { diff --git a/context/context.go b/context/context.go index 66650aa6..166455dc 100644 --- a/context/context.go +++ b/context/context.go @@ -14,6 +14,10 @@ type ( // IContext the interface for the iris/context // Used mostly inside packages which shouldn't be import ,directly, the kataras/iris. IContext interface { + // deprecated Start + PostFormValue(string) string + PostFormMulti(string) []string + // deprecated End Param(string) string ParamInt(string) (int, error) ParamInt64(string) (int64, error) @@ -29,8 +33,8 @@ type ( RequestIP() string RemoteAddr() string RequestHeader(k string) string - PostFormValue(string) string - PostFormMulti(string) []string + FormValueString(string) string + FormValues(string) []string SetStatusCode(int) SetContentType(string) SetHeader(string, string) diff --git a/deprecated.go b/deprecated.go new file mode 100644 index 00000000..4d24938e --- /dev/null +++ b/deprecated.go @@ -0,0 +1,82 @@ +package iris + +import "github.com/kataras/iris/config" + +/* Contains some different functions of context.go & iris.go which will be removed on the next revision */ + +// SecondaryListen same as .AddServer/.Servers.Add(config.Server) instead +// DEPRECATED: use .AddServer instead +// AddServers starts a server which listens to this station +// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) +// +// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station +// +// receives one parameter which is the config.Server for the new server +// returns the new standalone server( you can close this server by the returning reference) +// +// If you need only one server you can use the blocking-funcs: .Listen/ListenTLS/ListenUNIX/ListenTo +// +// this is a NOT A BLOCKING version, the main .Listen/ListenTLS/ListenUNIX/ListenTo should be always executed LAST, so this function goes before the main .Listen/ListenTLS/ListenUNIX/ListenTo +func SecondaryListen(cfg config.Server) *Server { + return Default.SecondaryListen(cfg) +} + +// SecondaryListen same as .AddServer/.Servers.Add(config.Server) instead +// DEPRECATED: use .AddServer instead +// AddServers starts a server which listens to this station +// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) +// +// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station +// +// receives one parameter which is the config.Server for the new server +// returns the new standalone server( you can close this server by the returning reference) +// +// If you need only one server you can use the blocking-funcs: .Listen/ListenTLS/ListenUNIX/ListenTo +// +// this is a NOT A BLOCKING version, the main .Listen/ListenTLS/ListenUNIX/ListenTo should be always executed LAST, so this function goes before the main .Listen/ListenTLS/ListenUNIX/ListenTo +func (s *Framework) SecondaryListen(cfg config.Server) *Server { + return s.Servers.Add(cfg) +} + +// NoListen is useful only when you want to test Iris, it doesn't starts the server but it configures and returns it +// DEPRECATED: use ListenVirtual instead +// initializes the whole framework but server doesn't listens to a specific net.Listener +// it is not blocking the app +func NoListen(optionalAddr ...string) *Server { + return Default.NoListen(optionalAddr...) +} + +// NoListen is useful only when you want to test Iris, it doesn't starts the server but it configures and returns it +// DEPRECATED: use ListenVirtual instead +// initializes the whole framework but server doesn't listens to a specific net.Listener +// it is not blocking the app +func (s *Framework) NoListen(optionalAddr ...string) *Server { + return s.ListenVirtual(optionalAddr...) +} + +// CloseWithErr terminates all the registered servers and returns an error if any +// DEPRECATED: use Close instead, and if you want to panic on errors : iris.Must(iris.Close()) +// if you want to panic on this error use the iris.Must(iris.Close()) +func CloseWithErr() error { + return Default.Close() +} + +// CloseWithErr terminates all the registered servers and returns an error if any +// DEPRECATED: use Close instead, and if you want to panic on errors : iris.Must(iris.Close()) +// if you want to panic on this error use the iris.Must(iris.Close()) +func (s *Framework) CloseWithErr() error { + return s.Close() +} + +// PostFormMulti returns a slice of string from post request's data +// DEPRECATED: Plase use FormValues instead +func (ctx *Context) PostFormMulti(name string) []string { + return ctx.FormValues(name) +} + +// PostFormValue This will be deprecated +///DEPRECATED: please use FormValueString instead +// PostFormValue returns a single value from post request's data +func (ctx *Context) PostFormValue(name string) string { + return ctx.FormValueString(name) +} diff --git a/iris.go b/iris.go index bad072e5..578fa141 100644 --- a/iris.go +++ b/iris.go @@ -81,7 +81,7 @@ import ( const ( // Version of the iris - Version = "3.0.0-rc.4" + Version = "3.0.0-pre.release" // HTMLEngine conversion for config.HTMLEngine HTMLEngine = config.HTMLEngine @@ -156,17 +156,14 @@ type ( FrameworkAPI interface { MuxAPI Must(error) + AddServer(config.Server) *Server ListenTo(config.Server) error - ListenWithErr(string) error Listen(string) - ListenTLSWithErr(string, string, string) error ListenTLS(string, string, string) - ListenUNIXWithErr(string, os.FileMode) error ListenUNIX(string, os.FileMode) - SecondaryListen(config.Server) *Server ListenVirtual(...string) *Server - NoListen(...string) *Server - Close() + Go() error + Close() error // global middleware prepending, registers to all subdomains, to all parties, you can call it at the last also MustUse(...Handler) MustUseFunc(...HandlerFunc) @@ -289,18 +286,17 @@ func (s *Framework) Go() error { // print the banner if !s.Config.DisableBanner { - serversMessage := time.Now().Format(config.TimeFormat) + ": Running at " + openedServers := s.Servers.GetAllOpened() - if len(openedServers) == 1 { - // if only one server then don't need to add a new line - serversMessage += openedServers[0].Host() - } else { - for _, srv := range openedServers { - serversMessage += "\n" + srv.Host() - } + l := len(openedServers) + hosts := make([]string, l, l) + for i, srv := range openedServers { + hosts[i] = srv.Host() } - s.Logger.PrintBanner(banner, serversMessage) + bannerMessage := time.Now().Format(config.TimeFormat) + ": Running at " + strings.Join(hosts, ", ") + s.Logger.PrintBanner(banner, bannerMessage) + } s.Plugins.DoPostListen(s) @@ -308,7 +304,7 @@ func (s *Framework) Go() error { go func() { s.Available <- true }() ch := make(chan os.Signal) <-ch - s.CloseWithErr() // btw, don't panic here + s.Close() // btw, don't panic here return nil } @@ -325,7 +321,44 @@ func (s *Framework) Must(err error) { } } +// AddServer same as .Servers.Add(config.Server) instead +// +// AddServers starts a server which listens to this station +// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) +// +// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station +// +// receives one parameter which is the config.Server for the new server +// returns the new standalone server( you can close this server by the returning reference) +// +// If you need only one server you can use the blocking-funcs: .Listen/ListenTLS/ListenUNIX/ListenTo +// +// this is a NOT A BLOCKING version, the main .Listen/ListenTLS/ListenUNIX/ListenTo should be always executed LAST, so this function goes before the main .Listen/ListenTLS/ListenUNIX/ListenTo +func AddServer(cfg config.Server) *Server { + return Default.AddServer(cfg) +} + +// AddServer same as .Servers.Add(config.Server) instead +// +// AddServers starts a server which listens to this station +// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) +// +// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station +// +// receives one parameter which is the config.Server for the new server +// returns the new standalone server( you can close this server by the returning reference) +// +// If you need only one server you can use the blocking-funcs: .Listen/ListenTLS/ListenUNIX/ListenTo +// +// this is a NOT A BLOCKING version, the main .Listen/ListenTLS/ListenUNIX/ListenTo should be always executed LAST, so this function goes before the main .Listen/ListenTLS/ListenUNIX/ListenTo +func (s *Framework) AddServer(cfg config.Server) *Server { + return s.Servers.Add(cfg) +} + // ListenTo listens to a server but receives the full server's configuration +// returns an error, you're responsible to handle that +// or use the iris.Must(iris.ListenTo(config.Server{})) +// // it's a blocking func func ListenTo(cfg config.Server) error { return Default.ListenTo(cfg) @@ -338,59 +371,24 @@ func (s *Framework) ListenTo(cfg config.Server) (err error) { return s.Go() } -// ListenWithErr starts the standalone http server -// which listens to the addr parameter which as the form of -// host:port -// -// It returns an error you are responsible how to handle this -// if you need a func to panic on error use the Listen -// ex: log.Fatal(iris.ListenWithErr(":8080")) -func ListenWithErr(addr string) error { - return Default.ListenWithErr(addr) -} - // Listen starts the standalone http server // which listens to the addr parameter which as the form of // host:port // -// It panics on error if you need a func to return an error use the ListenWithErr -// ex: iris.Listen(":8080") +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(config.Server{ListeningAddr:":8080"}) func Listen(addr string) { Default.Listen(addr) } -// ListenWithErr starts the standalone http server -// which listens to the addr parameter which as the form of -// host:port -// -// It returns an error you are responsible how to handle this -// if you need a func to panic on error use the Listen -// ex: log.Fatal(iris.ListenWithErr(":8080")) -func (s *Framework) ListenWithErr(addr string) error { - return s.ListenTo(config.Server{ListeningAddr: addr}) -} - // Listen starts the standalone http server // which listens to the addr parameter which as the form of // host:port // -// It panics on error if you need a func to return an error use the ListenWithErr -// ex: iris.Listen(":8080") +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(config.Server{ListeningAddr:":8080"}) func (s *Framework) Listen(addr string) { - s.Must(s.ListenWithErr(addr)) -} - -// ListenTLSWithErr Starts a https server with certificates, -// if you use this method the requests of the form of 'http://' will fail -// only https:// connections are allowed -// which listens to the addr parameter which as the form of -// host:port -// -// It returns an error you are responsible how to handle this -// if you need a func to panic on error use the ListenTLS -// ex: log.Fatal(iris.ListenTLSWithErr(":8080","yourfile.cert","yourfile.key")) -func ListenTLSWithErr(addr string, certFile string, keyFile string) error { - return Default.ListenTLSWithErr(addr, certFile, keyFile) + s.Must(s.ListenTo(config.Server{ListeningAddr: addr})) } // ListenTLS Starts a https server with certificates, @@ -399,114 +397,41 @@ func ListenTLSWithErr(addr string, certFile string, keyFile string) error { // which listens to the addr parameter which as the form of // host:port // -// It panics on error if you need a func to return an error use the ListenTLSWithErr -// ex: iris.ListenTLS(":8080","yourfile.cert","yourfile.key") +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(":8080","yourfile.cert","yourfile.key") func ListenTLS(addr string, certFile string, keyFile string) { Default.ListenTLS(addr, certFile, keyFile) } -// ListenTLSWithErr Starts a https server with certificates, -// if you use this method the requests of the form of 'http://' will fail -// only https:// connections are allowed -// which listens to the addr parameter which as the form of -// host:port -// -// It returns an error you are responsible how to handle this -// if you need a func to panic on error use the ListenTLS -// ex: log.Fatal(iris.ListenTLSWithErr(":8080","yourfile.cert","yourfile.key")) -func (s *Framework) ListenTLSWithErr(addr string, certFile string, keyFile string) error { - if certFile == "" || keyFile == "" { - return fmt.Errorf("You should provide certFile and keyFile for TLS/SSL") - } - return s.ListenTo(config.Server{ListeningAddr: addr, CertFile: certFile, KeyFile: keyFile}) -} - // ListenTLS Starts a https server with certificates, // if you use this method the requests of the form of 'http://' will fail // only https:// connections are allowed // which listens to the addr parameter which as the form of // host:port // -// It panics on error if you need a func to return an error use the ListenTLSWithErr -// ex: iris.ListenTLS(":8080","yourfile.cert","yourfile.key") +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(":8080","yourfile.cert","yourfile.key") func (s *Framework) ListenTLS(addr string, certFile, keyFile string) { - s.Must(s.ListenTLSWithErr(addr, certFile, keyFile)) -} - -// ListenUNIXWithErr starts the process of listening to the new requests using a 'socket file', this works only on unix -// returns an error if something bad happens when trying to listen to -func ListenUNIXWithErr(addr string, mode os.FileMode) error { - return Default.ListenUNIXWithErr(addr, mode) + if certFile == "" || keyFile == "" { + s.Logger.Panic("You should provide certFile and keyFile for TLS/SSL") + } + s.Must(s.ListenTo(config.Server{ListeningAddr: addr, CertFile: certFile, KeyFile: keyFile})) } // ListenUNIX starts the process of listening to the new requests using a 'socket file', this works only on unix -// panics on error +// +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(":8080", Mode: os.FileMode) func ListenUNIX(addr string, mode os.FileMode) { Default.ListenUNIX(addr, mode) } -// ListenUNIXWithErr starts the process of listening to the new requests using a 'socket file', this works only on unix -// returns an error if something bad happens when trying to listen to -func (s *Framework) ListenUNIXWithErr(addr string, mode os.FileMode) error { - return s.ListenTo(config.Server{ListeningAddr: addr, Mode: mode}) -} - // ListenUNIX starts the process of listening to the new requests using a 'socket file', this works only on unix -// panics on error +// +// It panics on error if you need a func to return an error, use the ListenTo +// ex: err := iris.ListenTo(":8080", Mode: os.FileMode) func (s *Framework) ListenUNIX(addr string, mode os.FileMode) { - s.Must(s.ListenUNIXWithErr(addr, mode)) -} - -// SecondaryListen NOTE: This will be deprecated -// Use .Servers.Add(config.Server) instead -// -// SecondaryListen starts a server which listens to this station -// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) -// -// this is useful only when you want to have two or more listening ports ( two or more servers ) for the same station -// -// receives one parameter which is the config.Server for the new server -// returns the new standalone server( you can close this server by the returning reference) -// -// If you need only one server this function is not for you, instead you must use the normal .Listen/ListenTLS functions. -// -// this is a NOT A BLOCKING version, the main iris.Listen should be always executed LAST, so this function goes before the main .Listen. -func SecondaryListen(cfg config.Server) *Server { - return Default.SecondaryListen(cfg) -} - -// SecondaryListen NOTE: This will be deprecated -// Use .Servers.Add(config.Server) instead -// -// SecondaryListen starts a server which listens to this station -// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https) -// -// this is useful only when you want to have two or more listening ports ( two or more servers ) for the same station -// -// receives one parameter which is the config.Server for the new server -// returns the new standalone server( you can close this server by the returning reference) -// -// If you need only one server this function is not for you, instead you must use the normal .Listen/ListenTLS functions. -// -// this is a NOT A BLOCKING version, the main iris.Listen should be always executed LAST, so this function goes before the main .Listen. -func (s *Framework) SecondaryListen(cfg config.Server) *Server { - return s.Servers.Add(cfg) -} - -// NoListen is useful only when you want to test Iris, it doesn't starts the server but it configures and returns it -// initializes the whole framework but server doesn't listens to a specific net.Listener -// it is not blocking the app -// same as ListenVirtual -func NoListen(optionalAddr ...string) *Server { - return Default.NoListen(optionalAddr...) -} - -// NoListen is useful only when you want to test Iris, it doesn't starts the server but it configures and returns it -// initializes the whole framework but server doesn't listens to a specific net.Listener -// it is not blocking the app -// same as ListenVirtual -func (s *Framework) NoListen(optionalAddr ...string) *Server { - return s.ListenVirtual(optionalAddr...) + s.Must(ListenTo(config.Server{ListeningAddr: addr, Mode: mode})) } // ListenVirtual is useful only when you want to test Iris, it doesn't starts the server but it configures and returns it @@ -540,28 +465,20 @@ func (s *Framework) ListenVirtual(optionalAddr ...string) *Server { return s.Servers.Main() } -// CloseWithErr terminates all the registered servers and returns an error if any -func CloseWithErr() error { - return Default.CloseWithErr() +// Close terminates all the registered servers and returns an error if any +// if you want to panic on this error use the iris.Must(iris.Close()) +func Close() error { + return Default.Close() } -//Close terminates all the registered servers and panic if error occurs -func Close() { - Default.Close() -} - -// CloseWithErr terminates all the registered servers and returns an error if any -func (s *Framework) CloseWithErr() error { +// Close terminates all the registered servers and returns an error if any +// if you want to panic on this error use the iris.Must(iris.Close()) +func (s *Framework) Close() error { s.Plugins.DoPreClose(s) s.Available = make(chan bool) return s.Servers.CloseAll() } -//Close terminates all the registered servers and panic if error occurs -func (s *Framework) Close() { - s.Must(s.CloseWithErr()) -} - // MustUse registers Handler middleware to the beginning, prepends them instead of append // // Use it when you want to add a global middleware to all parties, to all routes in all subdomains diff --git a/plugin_test.go b/plugin_test.go index b22daf02..67906e3e 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -74,7 +74,7 @@ func ExamplePlugins_Add() { fmt.Println(desc) ListenVirtual() - CloseWithErr() + Close() // Output: // GetName Struct