move sessions and websocket examples, gofmt, fix misspells and experimental optimizations 🍐

Former-commit-id: cae4f94bbd404d26ab13dade02b52f81feaddf24
This commit is contained in:
hiveminded 2017-07-22 22:57:20 +03:00
parent 90b8c1af44
commit 9a0b18acbf
36 changed files with 155 additions and 97 deletions

View File

@ -15,18 +15,6 @@ after_script:
- cd ./_examples
- go get ./...
- go test -v -cover ./...
# cache examples
- cd ../cache/_examples
- go get ./...
- go test -v -cover ./...
# sessions examples
- cd ../../sessions/_examples
- go get ./...
- go test -v -cover ./...
# websocket examples
- cd ../../websocket/_examples
- go get ./...
- go test -v -cover ./...
# typescript examples
- cd ../../typescript/_examples
- go get ./...

View File

@ -11,11 +11,11 @@
## 🔥 Reborn
As you may have heard I have huge responsibilities on my new position at Dubai nowdays, therefore I don't have the needed time to work on this project anymore.
As you may have heard I have huge responsibilities on my new position at Dubai nowadays, therefore I don't have the needed time to work on this project anymore.
After almost a month of negotiations and searching I succeed to find a decent software engineer to continue my work on the open source community.
The leadership of this, open-source, repository was transfered to [hiveminded](https://github.com/hiveminded).
The leadership of this, open-source, repository was transferred to [hiveminded](https://github.com/hiveminded).
These types of projects need heart and sacrifices to continue offer the best developer experience like a paid software, please do support him as you did with me!

View File

@ -23,7 +23,7 @@ No API Changes.
### Django view engine
@corebreaker pushed a [PR](https://github.com/kataras/iris/pull/682) to solve the [Problem for {%extends%} in Django Engine with embedded files](dhttps://github.com/kataras/iris/issues/681).
@corebreaker pushed a [PR](https://github.com/kataras/iris/pull/682) to solve the [Problem for {%extends%} in Django Engine with embedded files](https://github.com/kataras/iris/issues/681).
### Logger
@ -248,11 +248,11 @@ Despite the deflamations, the clickbait articles, the removed posts of mine at r
## 🔥 Reborn
As you may have heard I have huge responsibilities on my new position at Dubai nowdays, therefore I don't have the needed time to work on this project anymore.
As you may have heard I have huge responsibilities on my new position at Dubai nowadays, therefore I don't have the needed time to work on this project anymore.
After a month of negotiations and searching I succeed to find a decent software engineer to continue my work on the open source community.
The leadership of this, open-source, repository was transfered to [hiveminded](https://github.com/hiveminded), the author of iris-based [get-ion/ion](https://github.com/get-ion/ion), he actually did an excellent job on the framework, he kept the code as minimal as possible and at the same time added more features, examples and middleware(s).
The leadership of this, open-source, repository was transferred to [hiveminded](https://github.com/hiveminded), the author of iris-based [get-ion/ion](https://github.com/get-ion/ion), he actually did an excellent job on the framework, he kept the code as minimal as possible and at the same time added more features, examples and middleware(s).
These types of projects need heart and sacrifices to continue offer the best developer experience like a paid software, please do support him as you did with me!

View File

@ -61,11 +61,11 @@ Iris is a fast, simple and efficient micro web framework for Go. It provides a b
### 🔥 Reborn
As you may have heard I have huge responsibilities on my new position at Dubai nowdays, therefore I don't have the needed time to work on this project anymore.
As you may have heard I have huge responsibilities on my new position at Dubai nowadays, therefore I don't have the needed time to work on this project anymore.
After almost a month of negotiations and searching I succeed to find a decent software engineer to continue my work on the open source community.
The leadership of this, open-source, repository was transfered to [hiveminded](https://github.com/hiveminded).
The leadership of this, open-source, repository was transferred to [hiveminded](https://github.com/hiveminded).
These types of projects need heart and sacrifices to continue offer the best developer experience like a paid software, please do support him as you did with me!
@ -158,7 +158,7 @@ We expect Go version 1.9 to be released in August, however you can install Go 1.
### Installing Go 1.9beta2
1. Go to https://golang.org/dl/#go1.9beta2
2. Download a compatible, with your OS, archieve, i.e `go1.9beta2.windows-amd64.zip`
2. Download a compatible, with your OS, archive, i.e `go1.9beta2.windows-amd64.zip`
3. Unzip the contents of `go1.9beta2.windows-amd64.zip/go` folder to your $GOROOT, i.e `C:\Go`
4. Open a terminal and execute `go version`, it should output the go1.9beta2 version, i.e:
```sh
@ -282,7 +282,7 @@ Compared to the rest open source projects, this one is very active and you get a
* JWT
- Server
* Automatically install and serve certificates from https://letsencrypt.org when serving via TLS
* Gracefuly shutdown by-default
* Gracefully shutdown by-default
* Register on shutdown, error or interrupt events
* Attach more than one server, fully compatible with `net/http#Server`
- View system: supporting 5 template engines. Fully compatible with `html/template`

View File

@ -179,17 +179,32 @@ The `httptest` package is your way for end-to-end HTTP testing, it uses the http
### Caching
iris cache library lives on its own package: [https://github.com/kataras/iris/tree/master/cache](https://github.com/kataras/iris/tree/master/cache) **it contains examples**
iris cache library lives on its own [package](https://github.com/kataras/iris/tree/master/cache).
- [Simple](cache/simple/main.go)
> You're free to use your own favourite caching package if you'd like so.
### Sessions
iris session manager lives on its own [package](https://github.com/kataras/iris/tree/master/sessions).
iris session manager lives on its own package: [https://github.com/kataras/iris/tree/master/sessions](https://github.com/kataras/iris/tree/master/sessions) **it contains examples**
- [Overview](sessions/overview/main.go)
- [Standalone](sessions/standalone/main.go)
- [Secure Cookie](sessions/securecookie/main.go)
- [Flash Messages](sessions/flash-messages/main.go)
- [Database](sessions/database/main.go)
> You're free to use your own favourite sessions package if you'd like so.
### Websockets
iris websocket library lives on its own package: [https://github.com/kataras/iris/tree/master/websocket](https://github.com/kataras/iris/tree/master/websocket) **it contains examples**
iris websocket library lives on its own [package](https://github.com/kataras/iris/tree/master/websocket).
- [Chat](websocket/chat/main.go)
- [Native Messages](websocket/native-messages/main.go)
- [Connection List](websocket/connectionlist/main.go)
- [TLS Enabled](websocket/secure/main.go)
- [Custom Raw Go Client](websocket/custom-go-client/main.go)
> You're free to use your own favourite websockets package if you'd like so.

View File

@ -42,7 +42,6 @@ func main() {
Age: 25,
}
ctx.StatusCode(iris.StatusOK)
// Manually setting a content type: ctx.ContentType("application/javascript")
ctx.JSON(peter)
})
@ -83,5 +82,13 @@ func main() {
// http://localhost:8080/jsonp
// http://localhost:8080/xml
// http://localhost:8080/markdown
app.Run(iris.Addr(":8080"))
//
// `iris.WithOptimizations` is an optional configurator,
// if passed to the `Run` then it will ensure that the application
// response to the client as fast as possible.
//
//
// `iris.WithoutServerError` is an optional configurator,
// if passed to the `Run` then it will not print its passed error as an actual server error.
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations)
}

7
cache/README.md vendored
View File

@ -1,7 +0,0 @@
# Cache
Fast HTTP Cache support for the [iris](https://github.com/kataras/iris) web framework.
## Table of contents
* [Simple](_examples/simple/main.go)

View File

@ -15,9 +15,9 @@ var errConfigurationDecode = errors.New("error while trying to decode configurat
// YAML reads Configuration from a configuration.yml file.
//
// Accepts the absolute path of the configuration.yml.
// Accepts the absolute path of the cfg.yml.
// An error will be shown to the user via panic with the error message.
// Error may occur when the configuration.yml doesn't exists or is not formatted correctly.
// Error may occur when the cfg.yml doesn't exists or is not formatted correctly.
//
// Usage:
// app := iris.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.YAML("myconfig.yml")))
@ -138,42 +138,49 @@ var WithoutInterruptHandler = func(app *Application) {
// WithoutPathCorrection disables the PathCorrection setting.
//
// See` Configuration`.
// See `Configuration`.
var WithoutPathCorrection = func(app *Application) {
app.config.DisablePathCorrection = true
}
// WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting.
//
// See` Configuration`.
// See `Configuration`.
var WithoutBodyConsumptionOnUnmarshal = func(app *Application) {
app.config.DisableBodyConsumptionOnUnmarshal = true
}
// WithoutAutoFireStatusCode disables the AutoFireStatusCode setting.
//
// See` Configuration`.
// See `Configuration`.
var WithoutAutoFireStatusCode = func(app *Application) {
app.config.DisableAutoFireStatusCode = true
}
// WithPathEscape enanbles the PathEscape setting.
//
// See` Configuration`.
// See `Configuration`.
var WithPathEscape = func(app *Application) {
app.config.EnablePathEscape = true
}
// WithOptimizations can force the application to optimize for the best performance where is possible.
//
// See `Configuration`.
var WithOptimizations = func(app *Application) {
app.config.EnableOptimizations = true
}
// WithFireMethodNotAllowed enanbles the FireMethodNotAllowed setting.
//
// See` Configuration`.
// See `Configuration`.
var WithFireMethodNotAllowed = func(app *Application) {
app.config.FireMethodNotAllowed = true
}
// WithTimeFormat sets the TimeFormat setting.
//
// See` Configuration`.
// See `Configuration`.
func WithTimeFormat(timeformat string) Configurator {
return func(app *Application) {
app.config.TimeFormat = timeformat
@ -182,7 +189,7 @@ func WithTimeFormat(timeformat string) Configurator {
// WithCharset sets the Charset setting.
//
// See` Configuration`.
// See `Configuration`.
func WithCharset(charset string) Configurator {
return func(app *Application) {
app.config.Charset = charset
@ -227,7 +234,7 @@ func WithoutRemoteAddrHeader(headerName string) Configurator {
// WithOtherValue adds a value based on a key to the Other setting.
//
// See` Configuration`.
// See `Configuration`.
func WithOtherValue(key string, val interface{}) Configurator {
return func(app *Application) {
if app.config.Other == nil {
@ -290,6 +297,11 @@ type Configuration struct {
// Defaults to false.
EnablePathEscape bool `yaml:"EnablePathEscape" toml:"EnablePathEscape"`
// EnableOptimization when this field is true
// then the application tries to optimize for the best performance where is possible.
//
// Defaults to false.
EnableOptimizations bool `yaml:"EnableOptimizations" toml:"EnableOptimizations"`
// FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
// fires the 405 error instead of 404
// Defaults to false.
@ -366,10 +378,11 @@ type Configuration struct {
//
// Look `context.RemoteAddr()` for more.
RemoteAddrHeaders map[string]bool `yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
// Other are the custom, dynamic options, can be empty.
// This field used only by you to set any app's options you want
// or by custom adaptors, it's a way to simple communicate between your adaptors (if any)
// Defaults to a non-nil empty map
// Defaults to a non-nil empty map.
Other map[string]interface{} `yaml:"Other" toml:"Other"`
}
@ -384,7 +397,7 @@ func (c Configuration) GetVHost() string {
return c.vhost
}
// GetDisablePathCorrection returns the configuration.DisablePathCorrection,
// GetDisablePathCorrection returns the Configuration#DisablePathCorrection,
// DisablePathCorrection corrects and redirects the requested path to the registered path
// for example, if /home/ path is requested but no handler for this Route found,
// then the Router checks if /home handler exists, if yes,
@ -393,18 +406,24 @@ func (c Configuration) GetDisablePathCorrection() bool {
return c.DisablePathCorrection
}
// GetEnablePathEscape is the configuration.EnablePathEscape,
// GetEnablePathEscape is the Configuration#EnablePathEscape,
// returns true when its escapes the path, the named parameters (if any).
func (c Configuration) GetEnablePathEscape() bool {
return c.EnablePathEscape
}
// GetFireMethodNotAllowed returns the configuration.FireMethodNotAllowed.
// GetEnableOptimizations returns whether
// the application has performance optimizations enabled.
func (c Configuration) GetEnableOptimizations() bool {
return c.EnableOptimizations
}
// GetFireMethodNotAllowed returns the Configuration#FireMethodNotAllowed.
func (c Configuration) GetFireMethodNotAllowed() bool {
return c.FireMethodNotAllowed
}
// GetDisableBodyConsumptionOnUnmarshal returns the configuration.GetDisableBodyConsumptionOnUnmarshal,
// GetDisableBodyConsumptionOnUnmarshal returns the Configuration#GetDisableBodyConsumptionOnUnmarshal,
// manages the reading behavior of the context's body readers/binders.
// If returns true then the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`
// is disabled.
@ -417,19 +436,19 @@ func (c Configuration) GetDisableBodyConsumptionOnUnmarshal() bool {
return c.DisableBodyConsumptionOnUnmarshal
}
// GetDisableAutoFireStatusCode returns the configuration.DisableAutoFireStatusCode.
// GetDisableAutoFireStatusCode returns the Configuration#DisableAutoFireStatusCode.
// Returns true when the http error status code handler automatic execution turned off.
func (c Configuration) GetDisableAutoFireStatusCode() bool {
return c.DisableAutoFireStatusCode
}
// GetTimeFormat returns the configuration.TimeFormat,
// GetTimeFormat returns the Configuration#TimeFormat,
// format for any kind of datetime parsing.
func (c Configuration) GetTimeFormat() string {
return c.TimeFormat
}
// GetCharset returns the configuration.Charset,
// GetCharset returns the Configuration#Charset,
// the character encoding for various rendering
// used for templates and the rest of the responses.
func (c Configuration) GetCharset() string {
@ -476,7 +495,7 @@ func (c Configuration) GetRemoteAddrHeaders() map[string]bool {
return c.RemoteAddrHeaders
}
// GetOther returns the configuration.Other map.
// GetOther returns the Configuration#Other map.
func (c Configuration) GetOther() map[string]interface{} {
return c.Other
}
@ -513,6 +532,10 @@ func WithConfiguration(c Configuration) Configurator {
main.EnablePathEscape = v
}
if v := c.EnableOptimizations; v {
main.EnableOptimizations = v
}
if v := c.FireMethodNotAllowed; v {
main.FireMethodNotAllowed = v
}
@ -590,6 +613,7 @@ func DefaultConfiguration() Configuration {
"X-Forwarded-For": false,
"CF-Connecting-IP": false,
},
Other: make(map[string]interface{}, 0),
EnableOptimizations: false,
Other: make(map[string]interface{}, 0),
}
}

View File

@ -24,6 +24,10 @@ type ConfigurationReadOnly interface {
// returns true when its escapes the path, the named parameters (if any).
GetEnablePathEscape() bool
// GetEnableOptimizations returns whether
// the application has performance optimizations enabled.
GetEnableOptimizations() bool
// GetFireMethodNotAllowed returns the configuration.FireMethodNotAllowed.
GetFireMethodNotAllowed() bool
// GetDisableBodyConsumptionOnUnmarshal returns the configuration.GetDisableBodyConsumptionOnUnmarshal,

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/fatih/structs"
"github.com/json-iterator/go"
"github.com/microcosm-cc/bluemonday"
"github.com/monoculum/formam"
"github.com/russross/blackfriday"
@ -1344,16 +1345,22 @@ func (ctx *context) UnmarshalBody(v interface{}, unmarshaler Unmarshaler) error
return unmarshaler.Unmarshal(rawData, &v)
}
func (ctx *context) shouldOptimize() bool {
return ctx.Application().ConfigurationReadOnly().GetEnableOptimizations()
}
// ReadJSON reads JSON from request's body and binds it to a value of any json-valid type.
func (ctx *context) ReadJSON(jsonObject interface{}) error {
return ctx.UnmarshalBody(jsonObject, UnmarshalerFunc(json.Unmarshal))
var unmarshaler = json.Unmarshal
if ctx.shouldOptimize() {
unmarshaler = jsoniter.Unmarshal
}
return ctx.UnmarshalBody(jsonObject, UnmarshalerFunc(unmarshaler))
}
// ReadXML reads XML from request's body and binds it to a value of any xml-valid type.
func (ctx *context) ReadXML(xmlObject interface{}) error {
return ctx.UnmarshalBody(xmlObject, UnmarshalerFunc(xml.Unmarshal))
}
var (
@ -1780,15 +1787,28 @@ var (
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
// Ignores StatusCode, Gzip, StreamingJSON options.
func WriteJSON(writer io.Writer, v interface{}, options JSON) (int, error) {
var result []byte
var err error
func WriteJSON(writer io.Writer, v interface{}, options JSON, enableOptimization ...bool) (int, error) {
var (
result []byte
err error
optimize = len(enableOptimization) > 0 && enableOptimization[0]
)
if indent := options.Indent; indent != "" {
result, err = json.MarshalIndent(v, "", indent)
marshalIndent := json.MarshalIndent
if optimize {
marshalIndent = jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent
}
result, err = marshalIndent(v, "", indent)
result = append(result, newLineB...)
} else {
result, err = json.Marshal(v)
marshal := json.Marshal
if optimize {
marshal = jsoniter.ConfigCompatibleWithStandardLibrary.Marshal
}
result, err = marshal(v)
}
if err != nil {
@ -1811,20 +1831,32 @@ func WriteJSON(writer io.Writer, v interface{}, options JSON) (int, error) {
var defaultJSONOptions = JSON{}
// JSON marshals the given interface object and writes the JSON response to the client.
func (ctx *context) JSON(v interface{}, opts ...JSON) (int, error) {
func (ctx *context) JSON(v interface{}, opts ...JSON) (n int, err error) {
options := defaultJSONOptions
if len(opts) > 0 {
options = opts[0]
}
optimize := ctx.shouldOptimize()
ctx.ContentType(contentJSONHeaderValue)
if options.StreamingJSON {
enc := json.NewEncoder(ctx.writer)
enc.SetEscapeHTML(!options.UnescapeHTML)
enc.SetIndent(options.Prefix, options.Indent)
err := enc.Encode(v)
if optimize {
var jsoniterConfig = jsoniter.Config{
EscapeHTML: !options.UnescapeHTML,
IndentionStep: 4,
}.Froze()
enc := jsoniterConfig.NewEncoder(ctx.writer)
err = enc.Encode(v)
} else {
enc := json.NewEncoder(ctx.writer)
enc.SetEscapeHTML(!options.UnescapeHTML)
enc.SetIndent(options.Prefix, options.Indent)
err = enc.Encode(v)
}
if err != nil {
ctx.StatusCode(http.StatusInternalServerError) // it handles the fallback to normal mode here which also removes the gzip headers.
return 0, err
@ -1832,7 +1864,7 @@ func (ctx *context) JSON(v interface{}, opts ...JSON) (int, error) {
return ctx.writer.Written(), err
}
n, err := WriteJSON(ctx.writer, v, options)
n, err = WriteJSON(ctx.writer, v, options, optimize)
if err != nil {
ctx.StatusCode(http.StatusInternalServerError)
return 0, err
@ -1846,14 +1878,21 @@ var (
)
// WriteJSONP marshals the given interface object and writes the JSON response to the writer.
func WriteJSONP(writer io.Writer, v interface{}, options JSONP) (int, error) {
func WriteJSONP(writer io.Writer, v interface{}, options JSONP, enableOptimization ...bool) (int, error) {
if callback := options.Callback; callback != "" {
writer.Write([]byte(callback + "("))
defer writer.Write(finishCallbackB)
}
optimize := len(enableOptimization) > 0 && enableOptimization[0]
if indent := options.Indent; indent != "" {
result, err := json.MarshalIndent(v, "", indent)
marshalIndent := json.MarshalIndent
if optimize {
marshalIndent = jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent
}
result, err := marshalIndent(v, "", indent)
if err != nil {
return 0, err
}
@ -1861,7 +1900,12 @@ func WriteJSONP(writer io.Writer, v interface{}, options JSONP) (int, error) {
return writer.Write(result)
}
result, err := json.Marshal(v)
marshal := json.Marshal
if optimize {
marshal = jsoniter.ConfigCompatibleWithStandardLibrary.Marshal
}
result, err := marshal(v)
if err != nil {
return 0, err
}
@ -1880,7 +1924,7 @@ func (ctx *context) JSONP(v interface{}, opts ...JSONP) (int, error) {
ctx.ContentType(contentJavascriptHeaderValue)
n, err := WriteJSONP(ctx.writer, v, options)
n, err := WriteJSONP(ctx.writer, v, options, ctx.shouldOptimize())
if err != nil {
ctx.StatusCode(http.StatusInternalServerError)
return 0, err

View File

@ -105,7 +105,7 @@ func (su *Supervisor) newListener() (net.Listener, error) {
return l, nil
}
// RegisterOnError registers a function to call when errors occured by the underline http server.
// RegisterOnError registers a function to call when errors occurred by the underline http server.
func (su *Supervisor) RegisterOnError(cb func(error)) {
su.mu.Lock()
su.onErr = append(su.onErr, cb)

View File

@ -33,7 +33,7 @@ func WriteStartupLogOnServe(w io.Writer) func(TaskHost) {
}
// ShutdownOnInterrupt terminates the supervisor and its underline server when CMD+C/CTRL+C pressed.
// This function should be registerd on Interrupt.
// This function should be registered on Interrupt.
func ShutdownOnInterrupt(su *Supervisor, shutdownTimeout time.Duration) func() {
return func() {
ctx, cancel := context.WithTimeout(context.TODO(), shutdownTimeout)

View File

@ -301,6 +301,11 @@ func (nodes Nodes) findChild(path string, params []string) (*node, []string) {
if n.rootWildcard {
// println("return from n.rootWildcard")
// single root wildcard
if len(path) < 2 {
// do not remove that, it seems useless but it's not,
// we had an error while production, this fixes that.
path = "/" + path
}
return n, append(params, path[1:])
}

2
doc.go
View File

@ -261,7 +261,7 @@ Example code:
That's all with listening, you have the full control when you need it.
Let's continue by learning how to catch CONTROL+C/COMMAND+C or unix kill command and shutdown the server gracefuly.
Let's continue by learning how to catch CONTROL+C/COMMAND+C or unix kill command and shutdown the server gracefully.
Gracefully Shutdown on CONTROL+C/COMMAND+C or when kill command sent is ENABLED BY-DEFAULT.

View File

@ -32,7 +32,7 @@ type Config struct {
// Columns will display the logs as well formatted columns (bool).
// If custom `LogFunc` has been provided then this field is useless and users should
// use the `Columinize` function of the logger to get the ouput result as columns.
// use the `Columinize` function of the logger to get the output result as columns.
//
// Defaults to true.
Columns bool

View File

@ -1,11 +0,0 @@
# Sessions
Fast HTTP Sessions for the [iris](https://github.com/kataras/iris) web framework.
## Table of contents
* [Overview](_examples/overview/main.go)
* [Standalone](_examples/standalone/main.go)
* [Secure Cookie](_examples/securecookie/main.go)
* [Flash Messages](_examples/flash-messages/main.go)
* [Database](_examples/database/main.go)

View File

@ -1,11 +0,0 @@
# Websocket
Rich websocket support for the [iris](https://github.com/kataras/iris) web framework.
## Table of contents
* [Chat](_examples/chat/main.go)
* [Native Messages](_examples/native-messages/main.go)
* [Connection List](_examples/connectionlist/main.go)
* [TLS Enabled](_examples/secure/main.go)
* [Custom Raw Go Client](_examples/custom-go-client/main.go)