mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Nothing special here, read HISTORY.md
This commit is contained in:
parent
053588babd
commit
e4ab993760
10
HISTORY.md
10
HISTORY.md
|
@ -375,7 +375,7 @@ Downloads the [basic](https://github.com/iris-contrib/examples/tree/master/AIO_
|
||||||
**outline**
|
**outline**
|
||||||
```go
|
```go
|
||||||
|
|
||||||
// StaticEmbedded used when files are distrubuted inside the app executable, using go-bindata mostly
|
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||||
// First parameter is the request path, the path which the files in the vdir(second parameter) will be served to, for example "/static"
|
// First parameter is the request path, the path which the files in the vdir(second parameter) will be served to, for example "/static"
|
||||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||||
// Third parameter is the Asset function
|
// Third parameter is the Asset function
|
||||||
|
@ -832,7 +832,7 @@ iris.Set(iris.OptionDisableBanner(true))
|
||||||
|
|
||||||
**List** of all available options:
|
**List** of all available options:
|
||||||
```go
|
```go
|
||||||
// OptionDisablePathCorrection corrects and redirects the requested path to the registed path
|
// OptionDisablePathCorrection corrects and redirects the requested path to the registered path
|
||||||
// for example, if /home/ path is requested but no handler for this Route found,
|
// for example, if /home/ path is requested but no handler for this Route found,
|
||||||
// then the Router checks if /home handler exists, if yes,
|
// then the Router checks if /home handler exists, if yes,
|
||||||
// (permant)redirects the client to the correct path /home
|
// (permant)redirects the client to the correct path /home
|
||||||
|
@ -880,7 +880,7 @@ OptionTimeFormat(val string)
|
||||||
OptionCharset(val string)
|
OptionCharset(val string)
|
||||||
|
|
||||||
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
||||||
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
// If you don't want to enable it globally, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
||||||
// Default is false
|
// Default is false
|
||||||
OptionGzip(val bool)
|
OptionGzip(val bool)
|
||||||
|
|
||||||
|
@ -1124,7 +1124,7 @@ Notes: if you compare it with previous releases (13+ versions before v3 stable),
|
||||||
If you're **willing to donate** click [here](DONATIONS.md)!
|
If you're **willing to donate** click [here](DONATIONS.md)!
|
||||||
|
|
||||||
|
|
||||||
- `iris.Config.Gzip`, enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content. If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true}). It defaults to false
|
- `iris.Config.Gzip`, enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content. If you don't want to enable it globally, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true}). It defaults to false
|
||||||
|
|
||||||
|
|
||||||
- **Added** `config.Server.Name` as requested
|
- **Added** `config.Server.Name` as requested
|
||||||
|
@ -1551,7 +1551,7 @@ OnDisconnect(func(){})
|
||||||
We have some base-config's changed, these configs which are defaulted to true renamed to 'Disable+$oldName'
|
We have some base-config's changed, these configs which are defaulted to true renamed to 'Disable+$oldName'
|
||||||
```go
|
```go
|
||||||
|
|
||||||
// DisablePathCorrection corrects and redirects the requested path to the registed path
|
// 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,
|
// for example, if /home/ path is requested but no handler for this Route found,
|
||||||
// then the Router checks if /home handler exists, if yes,
|
// then the Router checks if /home handler exists, if yes,
|
||||||
// (permant)redirects the client to the correct path /home
|
// (permant)redirects the client to the correct path /home
|
||||||
|
|
|
@ -378,7 +378,7 @@ Serve files or directories, use the correct for your case, if you don't know whi
|
||||||
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
||||||
// Note that you have to call it on every favicon you have to serve automatically (dekstop, mobile and so on)
|
// Note that you have to call it on every favicon you have to serve automatically (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// panics on error
|
// panics on error
|
||||||
Favicon(favPath string, requestPath ...string) RouteNameFunc
|
Favicon(favPath string, requestPath ...string) RouteNameFunc
|
||||||
|
@ -393,7 +393,7 @@ StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool)
|
||||||
// second parameter is the system directory (string)
|
// second parameter is the system directory (string)
|
||||||
StaticWeb(reqPath string, systemPath string) RouteNameFunc
|
StaticWeb(reqPath string, systemPath string) RouteNameFunc
|
||||||
|
|
||||||
// StaticEmbedded used when files are distrubuted inside the app executable, using go-bindata mostly
|
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||||
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
||||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||||
// Third parameter is the Asset function
|
// Third parameter is the Asset function
|
||||||
|
|
|
@ -119,7 +119,7 @@ type Configuration struct {
|
||||||
// Default is false
|
// Default is false
|
||||||
CheckForUpdatesSync bool
|
CheckForUpdatesSync bool
|
||||||
|
|
||||||
// DisablePathCorrection corrects and redirects the requested path to the registed path
|
// 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,
|
// for example, if /home/ path is requested but no handler for this Route found,
|
||||||
// then the Router checks if /home handler exists, if yes,
|
// then the Router checks if /home handler exists, if yes,
|
||||||
// (permant)redirects the client to the correct path /home
|
// (permant)redirects the client to the correct path /home
|
||||||
|
@ -177,7 +177,7 @@ type Configuration struct {
|
||||||
Charset string
|
Charset string
|
||||||
|
|
||||||
// Gzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
// Gzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
||||||
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
// If you don't want to enable it globally, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
||||||
// Defaults to false
|
// Defaults to false
|
||||||
Gzip bool
|
Gzip bool
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ var (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OptionDisablePathCorrection corrects and redirects the requested path to the registed path
|
// OptionDisablePathCorrection corrects and redirects the requested path to the registered path
|
||||||
// for example, if /home/ path is requested but no handler for this Route found,
|
// for example, if /home/ path is requested but no handler for this Route found,
|
||||||
// then the Router checks if /home handler exists, if yes,
|
// then the Router checks if /home handler exists, if yes,
|
||||||
// (permant)redirects the client to the correct path /home
|
// (permant)redirects the client to the correct path /home
|
||||||
|
@ -401,7 +401,7 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
||||||
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
// If you don't want to enable it globally, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
||||||
// Default is false
|
// Default is false
|
||||||
OptionGzip = func(val bool) OptionSet {
|
OptionGzip = func(val bool) OptionSet {
|
||||||
return func(c *Configuration) {
|
return func(c *Configuration) {
|
||||||
|
|
10
context.go
10
context.go
|
@ -64,7 +64,7 @@ const (
|
||||||
// CacheControl "Cache-Control"
|
// CacheControl "Cache-Control"
|
||||||
cacheControl = "Cache-Control"
|
cacheControl = "Cache-Control"
|
||||||
|
|
||||||
// stopExecutionPosition used inside the Context, is the number which shows us that the context's middleware manualy stop the execution
|
// stopExecutionPosition used inside the Context, is the number which shows us that the context's middleware manually stop the execution
|
||||||
stopExecutionPosition = 255
|
stopExecutionPosition = 255
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ type (
|
||||||
Request *http.Request
|
Request *http.Request
|
||||||
values requestValues
|
values requestValues
|
||||||
framework *Framework
|
framework *Framework
|
||||||
//keep track all registed middleware (handlers)
|
//keep track all registered middleware (handlers)
|
||||||
Middleware Middleware // exported because is useful for debugging
|
Middleware Middleware // exported because is useful for debugging
|
||||||
session sessions.Session
|
session sessions.Session
|
||||||
// Pos is the position number of the Context, look .Next to understand
|
// Pos is the position number of the Context, look .Next to understand
|
||||||
|
@ -313,7 +313,7 @@ func (ctx *Context) URLParam(key string) string {
|
||||||
return ctx.Request.URL.Query().Get(key)
|
return ctx.Request.URL.Query().Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// URLParams returns a map of GET query parameters seperated by comma if more than one
|
// URLParams returns a map of GET query parameters separated by comma if more than one
|
||||||
// it returns an empty map if nothing founds
|
// it returns an empty map if nothing founds
|
||||||
func (ctx *Context) URLParams() map[string]string {
|
func (ctx *Context) URLParams() map[string]string {
|
||||||
values := map[string]string{}
|
values := map[string]string{}
|
||||||
|
@ -1192,7 +1192,7 @@ func (ctx *Context) RemoveCookie(name string) {
|
||||||
c.Expires = exp
|
c.Expires = exp
|
||||||
c.MaxAge = -1
|
c.MaxAge = -1
|
||||||
ctx.SetCookie(c)
|
ctx.SetCookie(c)
|
||||||
// delete request's cookie also, which is temporarly available
|
// delete request's cookie also, which is temporary available
|
||||||
ctx.Request.Header.Set("Cookie", "")
|
ctx.Request.Header.Set("Cookie", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,7 +1292,7 @@ var errTransactionInterrupted = errors.New("Transaction Interrupted, recovery fr
|
||||||
// BeginTransaction starts a scoped transaction.
|
// BeginTransaction starts a scoped transaction.
|
||||||
//
|
//
|
||||||
// Can't say a lot here because it will take more than 200 lines to write about.
|
// Can't say a lot here because it will take more than 200 lines to write about.
|
||||||
// You can search third-party articles or books on how Business Transaction works (it's quite simple, especialy here).
|
// You can search third-party articles or books on how Business Transaction works (it's quite simple, especially here).
|
||||||
//
|
//
|
||||||
// Note that this is unique and new
|
// Note that this is unique and new
|
||||||
// (=I haver never seen any other examples or code in Golang on this subject, so far, as with the most of iris features...)
|
// (=I haver never seen any other examples or code in Golang on this subject, so far, as with the most of iris features...)
|
||||||
|
|
|
@ -684,7 +684,7 @@ func TestTransactions(t *testing.T) {
|
||||||
|
|
||||||
// OPTIONAl STEP:
|
// OPTIONAl STEP:
|
||||||
// but useful if we want to post back an error message to the client if the transaction failed.
|
// but useful if we want to post back an error message to the client if the transaction failed.
|
||||||
// if the reason is empty then the transaction completed succesfuly,
|
// if the reason is empty then the transaction completed successfully,
|
||||||
// otherwise we rollback the whole response body and cookies and everything lives inside the transaction.Request.
|
// otherwise we rollback the whole response body and cookies and everything lives inside the transaction.Request.
|
||||||
t.Complete(err)
|
t.Complete(err)
|
||||||
}
|
}
|
||||||
|
|
8
http.go
8
http.go
|
@ -697,7 +697,7 @@ type (
|
||||||
Path() string
|
Path() string
|
||||||
// SetPath changes/sets the path for this route
|
// SetPath changes/sets the path for this route
|
||||||
SetPath(string)
|
SetPath(string)
|
||||||
// Middleware returns the slice of Handler([]Handler) registed to this route
|
// Middleware returns the slice of Handler([]Handler) registered to this route
|
||||||
Middleware() Middleware
|
Middleware() Middleware
|
||||||
// SetMiddleware changes/sets the middleware(handler(s)) for this route
|
// SetMiddleware changes/sets the middleware(handler(s)) for this route
|
||||||
SetMiddleware(Middleware)
|
SetMiddleware(Middleware)
|
||||||
|
@ -817,9 +817,9 @@ func (r *route) hasCors() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// subdomainIndicator where './' exists in a registed path then it contains subdomain
|
// subdomainIndicator where './' exists in a registered path then it contains subdomain
|
||||||
subdomainIndicator = "./"
|
subdomainIndicator = "./"
|
||||||
// dynamicSubdomainIndicator where a registed path starts with '*.' then it contains a dynamic subdomain, if subdomain == "*." then its dynamic
|
// dynamicSubdomainIndicator where a registered path starts with '*.' then it contains a dynamic subdomain, if subdomain == "*." then its dynamic
|
||||||
dynamicSubdomainIndicator = "*."
|
dynamicSubdomainIndicator = "*."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -958,7 +958,7 @@ func (mux *serveMux) build() (methodEqual func(string, string) bool) {
|
||||||
tree = &muxTree{method: r.method, subdomain: r.subdomain, entry: &muxEntry{}}
|
tree = &muxTree{method: r.method, subdomain: r.subdomain, entry: &muxEntry{}}
|
||||||
mux.garden = append(mux.garden, tree)
|
mux.garden = append(mux.garden, tree)
|
||||||
}
|
}
|
||||||
// I decide that it's better to explicit give subdomain and a path to it than registedPath(mysubdomain./something) now its: subdomain: mysubdomain., path: /something
|
// I decide that it's better to explicit give subdomain and a path to it than registeredPath(mysubdomain./something) now its: subdomain: mysubdomain., path: /something
|
||||||
// we have different tree for each of subdomains, now you can use everything you can use with the normal paths ( before you couldn't set /any/*path)
|
// we have different tree for each of subdomains, now you can use everything you can use with the normal paths ( before you couldn't set /any/*path)
|
||||||
if err := tree.entry.add(r.path, r.middleware); err != nil {
|
if err := tree.entry.add(r.path, r.middleware); err != nil {
|
||||||
mux.logger.Panic(err)
|
mux.logger.Panic(err)
|
||||||
|
|
75
http_test.go
75
http_test.go
|
@ -293,7 +293,7 @@ type testRoute struct {
|
||||||
|
|
||||||
func TestMuxSimple(t *testing.T) {
|
func TestMuxSimple(t *testing.T) {
|
||||||
testRoutes := []testRoute{
|
testRoutes := []testRoute{
|
||||||
// FOUND - registed
|
// FOUND - registered
|
||||||
{"GET", "/test_get", "/test_get", "", "hello, get!", 200, true, nil, nil},
|
{"GET", "/test_get", "/test_get", "", "hello, get!", 200, true, nil, nil},
|
||||||
{"POST", "/test_post", "/test_post", "", "hello, post!", 200, true, nil, nil},
|
{"POST", "/test_post", "/test_post", "", "hello, post!", 200, true, nil, nil},
|
||||||
{"PUT", "/test_put", "/test_put", "", "hello, put!", 200, true, nil, nil},
|
{"PUT", "/test_put", "/test_put", "", "hello, put!", 200, true, nil, nil},
|
||||||
|
@ -303,7 +303,7 @@ func TestMuxSimple(t *testing.T) {
|
||||||
{"CONNECT", "/test_connect", "/test_connect", "", "hello, connect!", 200, true, nil, nil},
|
{"CONNECT", "/test_connect", "/test_connect", "", "hello, connect!", 200, true, nil, nil},
|
||||||
{"PATCH", "/test_patch", "/test_patch", "", "hello, patch!", 200, true, nil, nil},
|
{"PATCH", "/test_patch", "/test_patch", "", "hello, patch!", 200, true, nil, nil},
|
||||||
{"TRACE", "/test_trace", "/test_trace", "", "hello, trace!", 200, true, nil, nil},
|
{"TRACE", "/test_trace", "/test_trace", "", "hello, trace!", 200, true, nil, nil},
|
||||||
// NOT FOUND - not registed
|
// NOT FOUND - not registered
|
||||||
{"GET", "/test_get_nofound", "/test_get_nofound", "", "Not Found", 404, false, nil, nil},
|
{"GET", "/test_get_nofound", "/test_get_nofound", "", "Not Found", 404, false, nil, nil},
|
||||||
{"POST", "/test_post_nofound", "/test_post_nofound", "", "Not Found", 404, false, nil, nil},
|
{"POST", "/test_post_nofound", "/test_post_nofound", "", "Not Found", 404, false, nil, nil},
|
||||||
{"PUT", "/test_put_nofound", "/test_put_nofound", "", "Not Found", 404, false, nil, nil},
|
{"PUT", "/test_put_nofound", "/test_put_nofound", "", "Not Found", 404, false, nil, nil},
|
||||||
|
@ -519,7 +519,7 @@ func TestMuxCustomErrors(t *testing.T) {
|
||||||
notFoundMessage = "Iris custom message for 404 not found"
|
notFoundMessage = "Iris custom message for 404 not found"
|
||||||
internalServerMessage = "Iris custom message for 500 internal server error"
|
internalServerMessage = "Iris custom message for 500 internal server error"
|
||||||
testRoutesCustomErrors = []testRoute{
|
testRoutesCustomErrors = []testRoute{
|
||||||
// NOT FOUND CUSTOM ERRORS - not registed
|
// NOT FOUND CUSTOM ERRORS - not registered
|
||||||
{"GET", "/test_get_nofound_custom", "/test_get_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"GET", "/test_get_nofound_custom", "/test_get_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
{"POST", "/test_post_nofound_custom", "/test_post_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"POST", "/test_post_nofound_custom", "/test_post_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
{"PUT", "/test_put_nofound_custom", "/test_put_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"PUT", "/test_put_nofound_custom", "/test_put_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
|
@ -529,7 +529,7 @@ func TestMuxCustomErrors(t *testing.T) {
|
||||||
{"CONNECT", "/test_connect_nofound_custom", "/test_connect_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"CONNECT", "/test_connect_nofound_custom", "/test_connect_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
{"PATCH", "/test_patch_nofound_custom", "/test_patch_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"PATCH", "/test_patch_nofound_custom", "/test_patch_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
{"TRACE", "/test_trace_nofound_custom", "/test_trace_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
{"TRACE", "/test_trace_nofound_custom", "/test_trace_nofound_custom", "", notFoundMessage, 404, false, nil, nil},
|
||||||
// SERVER INTERNAL ERROR 500 PANIC CUSTOM ERRORS - registed
|
// SERVER INTERNAL ERROR 500 PANIC CUSTOM ERRORS - registered
|
||||||
{"GET", "/test_get_panic_custom", "/test_get_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
{"GET", "/test_get_panic_custom", "/test_get_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
||||||
{"POST", "/test_post_panic_custom", "/test_post_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
{"POST", "/test_post_panic_custom", "/test_post_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
||||||
{"PUT", "/test_put_panic_custom", "/test_put_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
{"PUT", "/test_put_panic_custom", "/test_put_panic_custom", "", internalServerMessage, 500, true, nil, nil},
|
||||||
|
@ -618,7 +618,7 @@ func TestMuxAPI(t *testing.T) {
|
||||||
}}
|
}}
|
||||||
|
|
||||||
iris.API("/users", testUserAPI{}, h...)
|
iris.API("/users", testUserAPI{}, h...)
|
||||||
// test a simple .Party with compination of .API
|
// test a simple .Party with combination of .API
|
||||||
iris.Party("sites/:site").API("/users", testUserAPI{}, h...)
|
iris.Party("sites/:site").API("/users", testUserAPI{}, h...)
|
||||||
|
|
||||||
e := httptest.New(iris.Default, t)
|
e := httptest.New(iris.Default, t)
|
||||||
|
@ -716,70 +716,6 @@ func TestMuxFireMethodNotAllowed(t *testing.T) {
|
||||||
iris.Close()
|
iris.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
var (
|
|
||||||
cacheDuration = 2 * time.Second
|
|
||||||
errCacheTestFailed = errors.New("Expected the main handler to be executed %d times instead of %d.")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ~14secs
|
|
||||||
func runCacheTest(e *httpexpect.Expect, path string, counterPtr *uint32, expectedBodyStr, expectedContentType string) error {
|
|
||||||
e.GET(path).Expect().Status(iris.StatusOK).Body().Equal(expectedBodyStr)
|
|
||||||
time.Sleep(cacheDuration / 5) // lets wait for a while, cache should be saved and ready
|
|
||||||
e.GET(path).Expect().Status(iris.StatusOK).Body().Equal(expectedBodyStr)
|
|
||||||
counter := atomic.LoadUint32(counterPtr)
|
|
||||||
if counter > 1 {
|
|
||||||
// n should be 1 because it doesn't changed after the first call
|
|
||||||
return errCacheTestFailed.Format(1, counter)
|
|
||||||
}
|
|
||||||
time.Sleep(cacheDuration)
|
|
||||||
|
|
||||||
// cache should be cleared now
|
|
||||||
e.GET(path).Expect().Status(iris.StatusOK).ContentType(expectedContentType, "utf-8").Body().Equal(expectedBodyStr)
|
|
||||||
time.Sleep(cacheDuration / 5)
|
|
||||||
// let's call again , the cache should be saved
|
|
||||||
e.GET(path).Expect().Status(iris.StatusOK).ContentType(expectedContentType, "utf-8").Body().Equal(expectedBodyStr)
|
|
||||||
counter = atomic.LoadUint32(counterPtr)
|
|
||||||
if counter != 2 {
|
|
||||||
return errCacheTestFailed.Format(2, counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Inside github.com/geekypanda/httpcache are enough, no need to add 10+ seconds of testing here.
|
|
||||||
func TestCache(t *testing.T) {
|
|
||||||
|
|
||||||
iris.ResetDefault()
|
|
||||||
|
|
||||||
expectedBodyStr := "Imagine it as a big message to achieve x20 response performance!"
|
|
||||||
var textCounter, htmlCounter uint32
|
|
||||||
|
|
||||||
iris.Get("/text", iris.Cache(func(ctx *iris.Context) {
|
|
||||||
atomic.AddUint32(&textCounter, 1)
|
|
||||||
ctx.Text(iris.StatusOK, expectedBodyStr)
|
|
||||||
}, cacheDuration))
|
|
||||||
|
|
||||||
iris.Get("/html", iris.Cache(func(ctx *iris.Context) {
|
|
||||||
atomic.AddUint32(&htmlCounter, 1)
|
|
||||||
ctx.HTML(iris.StatusOK, expectedBodyStr)
|
|
||||||
}, cacheDuration))
|
|
||||||
|
|
||||||
e := httptest.New(iris.Default, t)
|
|
||||||
|
|
||||||
// test cache on text/plain
|
|
||||||
if err := runCacheTest(e, "/text", &textCounter, expectedBodyStr, "text/plain"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// text cache on text/html
|
|
||||||
if err := runCacheTest(e, "/html", &htmlCounter, expectedBodyStr, "text/html"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func TestRedirectHTTPS(t *testing.T) {
|
func TestRedirectHTTPS(t *testing.T) {
|
||||||
|
|
||||||
api := iris.New(iris.OptionIsDevelopment(true))
|
api := iris.New(iris.OptionIsDevelopment(true))
|
||||||
|
@ -794,5 +730,4 @@ func TestRedirectHTTPS(t *testing.T) {
|
||||||
|
|
||||||
e := httptest.New(api, t)
|
e := httptest.New(api, t)
|
||||||
e.GET("/redirect").Expect().Status(iris.StatusOK).Body().Equal(expectedBody)
|
e.GET("/redirect").Expect().Status(iris.StatusOK).Body().Equal(expectedBody)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
75
iris.go
75
iris.go
|
@ -335,12 +335,12 @@ func (s *Framework) Set(setters ...OptionSetter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must panics on error, it panics on registed iris' logger
|
// Must panics on error, it panics on registered iris' logger
|
||||||
func Must(err error) {
|
func Must(err error) {
|
||||||
Default.Must(err)
|
Default.Must(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must panics on error, it panics on registed iris' logger
|
// Must panics on error, it panics on registered iris' logger
|
||||||
func (s *Framework) Must(err error) {
|
func (s *Framework) Must(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// s.Logger.Panicf("%s. Trace:\n%s", err, debug.Stack())
|
// s.Logger.Panicf("%s. Trace:\n%s", err, debug.Stack())
|
||||||
|
@ -411,7 +411,7 @@ func (s *Framework) Build() {
|
||||||
s.mux.setFireMethodNotAllowed(s.Config.FireMethodNotAllowed)
|
s.mux.setFireMethodNotAllowed(s.Config.FireMethodNotAllowed)
|
||||||
|
|
||||||
// prepare the server's handler, we do that check because iris supports
|
// prepare the server's handler, we do that check because iris supports
|
||||||
// custom routers (you can take the routes registed by iris using iris.Lookups function)
|
// custom routers (you can take the routes registered by iris using iris.Lookups function)
|
||||||
if s.Router == nil {
|
if s.Router == nil {
|
||||||
// build and get the default mux' handler(*Context)
|
// build and get the default mux' handler(*Context)
|
||||||
serve := s.mux.BuildHandler()
|
serve := s.mux.BuildHandler()
|
||||||
|
@ -437,6 +437,7 @@ func (s *Framework) Build() {
|
||||||
ConnState: s.Config.ConnState,
|
ConnState: s.Config.ConnState,
|
||||||
Handler: s.Router,
|
Handler: s.Router,
|
||||||
Addr: s.Config.VHost,
|
Addr: s.Config.VHost,
|
||||||
|
ErrorLog: s.Logger,
|
||||||
}
|
}
|
||||||
if s.Config.TLSNextProto != nil {
|
if s.Config.TLSNextProto != nil {
|
||||||
s.srv.TLSNextProto = s.Config.TLSNextProto
|
s.srv.TLSNextProto = s.Config.TLSNextProto
|
||||||
|
@ -973,17 +974,17 @@ func (s *Framework) UseGlobalFunc(handlersFn ...HandlerFunc) {
|
||||||
s.UseGlobal(convertToHandlers(handlersFn)...)
|
s.UseGlobal(convertToHandlers(handlersFn)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup returns a registed route by its name
|
// Lookup returns a registered route by its name
|
||||||
func Lookup(routeName string) Route {
|
func Lookup(routeName string) Route {
|
||||||
return Default.Lookup(routeName)
|
return Default.Lookup(routeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookups returns all registed routes
|
// Lookups returns all registered routes
|
||||||
func Lookups() []Route {
|
func Lookups() []Route {
|
||||||
return Default.Lookups()
|
return Default.Lookups()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup returns a registed route by its name
|
// Lookup returns a registered route by its name
|
||||||
func (s *Framework) Lookup(routeName string) Route {
|
func (s *Framework) Lookup(routeName string) Route {
|
||||||
r := s.mux.lookup(routeName)
|
r := s.mux.lookup(routeName)
|
||||||
if nil == r {
|
if nil == r {
|
||||||
|
@ -992,7 +993,7 @@ func (s *Framework) Lookup(routeName string) Route {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookups returns all registed routes
|
// Lookups returns all registered routes
|
||||||
func (s *Framework) Lookups() (routes []Route) {
|
func (s *Framework) Lookups() (routes []Route) {
|
||||||
// silly but...
|
// silly but...
|
||||||
for i := range s.mux.lookups {
|
for i := range s.mux.lookups {
|
||||||
|
@ -1411,27 +1412,27 @@ func (api *muxAPI) DoneFunc(handlersFn ...HandlerFunc) MuxAPI {
|
||||||
|
|
||||||
// Handle registers a route to the server's router
|
// Handle registers a route to the server's router
|
||||||
// if empty method is passed then registers handler(s) for all methods, same as .Any, but returns nil as result
|
// if empty method is passed then registers handler(s) for all methods, same as .Any, but returns nil as result
|
||||||
func Handle(method string, registedPath string, handlers ...Handler) RouteNameFunc {
|
func Handle(method string, registeredPath string, handlers ...Handler) RouteNameFunc {
|
||||||
return Default.Handle(method, registedPath, handlers...)
|
return Default.Handle(method, registeredPath, handlers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleFunc registers and returns a route with a method string, path string and a handler
|
// HandleFunc registers and returns a route with a method string, path string and a handler
|
||||||
// registedPath is the relative url path
|
// registeredPath is the relative url path
|
||||||
func HandleFunc(method string, registedPath string, handlersFn ...HandlerFunc) RouteNameFunc {
|
func HandleFunc(method string, registeredPath string, handlersFn ...HandlerFunc) RouteNameFunc {
|
||||||
return Default.HandleFunc(method, registedPath, handlersFn...)
|
return Default.HandleFunc(method, registeredPath, handlersFn...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle registers a route to the server's router
|
// Handle registers a route to the server's router
|
||||||
// if empty method is passed then registers handler(s) for all methods, same as .Any, but returns nil as result
|
// if empty method is passed then registers handler(s) for all methods, same as .Any, but returns nil as result
|
||||||
func (api *muxAPI) Handle(method string, registedPath string, handlers ...Handler) RouteNameFunc {
|
func (api *muxAPI) Handle(method string, registeredPath string, handlers ...Handler) RouteNameFunc {
|
||||||
if method == "" { // then use like it was .Any
|
if method == "" { // then use like it was .Any
|
||||||
for _, k := range AllMethods {
|
for _, k := range AllMethods {
|
||||||
api.Handle(k, registedPath, handlers...)
|
api.Handle(k, registeredPath, handlers...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpath := api.relativePath + registedPath // for now, keep the last "/" if any, "/xyz/"
|
fullpath := api.relativePath + registeredPath // for now, keep the last "/" if any, "/xyz/"
|
||||||
|
|
||||||
middleware := joinMiddleware(api.middleware, handlers)
|
middleware := joinMiddleware(api.middleware, handlers)
|
||||||
|
|
||||||
|
@ -1450,7 +1451,7 @@ func (api *muxAPI) Handle(method string, registedPath string, handlers ...Handle
|
||||||
//: /beta/ then should disable the path correction OR register it like: beta.Get("//")
|
//: /beta/ then should disable the path correction OR register it like: beta.Get("//")
|
||||||
// this is only for the party's roots in order to have expected paths,
|
// this is only for the party's roots in order to have expected paths,
|
||||||
// as we do with iris.Get("/") which is localhost:8080 as RFC points, not localhost:8080/
|
// as we do with iris.Get("/") which is localhost:8080 as RFC points, not localhost:8080/
|
||||||
if api.mux.correctPath && registedPath == slash { // check the given relative path
|
if api.mux.correctPath && registeredPath == slash { // check the given relative path
|
||||||
// remove last "/" if any, "/xyz/"
|
// remove last "/" if any, "/xyz/"
|
||||||
if len(path) > 1 { // if it's the root, then keep it*
|
if len(path) > 1 { // if it's the root, then keep it*
|
||||||
if path[len(path)-1] == slashByte {
|
if path[len(path)-1] == slashByte {
|
||||||
|
@ -1473,9 +1474,9 @@ func (api *muxAPI) Handle(method string, registedPath string, handlers ...Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleFunc registers and returns a route with a method string, path string and a handler
|
// HandleFunc registers and returns a route with a method string, path string and a handler
|
||||||
// registedPath is the relative url path
|
// registeredPath is the relative url path
|
||||||
func (api *muxAPI) HandleFunc(method string, registedPath string, handlersFn ...HandlerFunc) RouteNameFunc {
|
func (api *muxAPI) HandleFunc(method string, registeredPath string, handlersFn ...HandlerFunc) RouteNameFunc {
|
||||||
return api.Handle(method, registedPath, convertToHandlers(handlersFn)...)
|
return api.Handle(method, registeredPath, convertToHandlers(handlersFn)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// API converts & registers a custom struct to the router
|
// API converts & registers a custom struct to the router
|
||||||
|
@ -1484,7 +1485,7 @@ func (api *muxAPI) HandleFunc(method string, registedPath string, handlersFn ...
|
||||||
// second is the custom struct (interface{}) which can be anything that has a *iris.Context as field.
|
// second is the custom struct (interface{}) which can be anything that has a *iris.Context as field.
|
||||||
// third is the common middlewares, it's optional
|
// third is the common middlewares, it's optional
|
||||||
//
|
//
|
||||||
// Note that API's routes have their default-name to the full registed path,
|
// Note that API's routes have their default-name to the full registered path,
|
||||||
// no need to give a special name for it, because it's not supposed to be used inside your templates.
|
// no need to give a special name for it, because it's not supposed to be used inside your templates.
|
||||||
//
|
//
|
||||||
// Recommend to use when you retrieve data from an external database,
|
// Recommend to use when you retrieve data from an external database,
|
||||||
|
@ -1501,7 +1502,7 @@ func API(path string, restAPI HandlerAPI, middleware ...HandlerFunc) {
|
||||||
// second is the custom struct (interface{}) which can be anything that has a *iris.Context as field.
|
// second is the custom struct (interface{}) which can be anything that has a *iris.Context as field.
|
||||||
// third is the common middleware, it's optional
|
// third is the common middleware, it's optional
|
||||||
//
|
//
|
||||||
// Note that API's routes have their default-name to the full registed path,
|
// Note that API's routes have their default-name to the full registered path,
|
||||||
// no need to give a special name for it, because it's not supposed to be used inside your templates.
|
// no need to give a special name for it, because it's not supposed to be used inside your templates.
|
||||||
//
|
//
|
||||||
// Recommend to use when you retrieve data from an external database,
|
// Recommend to use when you retrieve data from an external database,
|
||||||
|
@ -1509,7 +1510,7 @@ func API(path string, restAPI HandlerAPI, middleware ...HandlerFunc) {
|
||||||
//
|
//
|
||||||
// This is a slow method, if you care about router-performance use the Handle/HandleFunc/Get/Post/Put/Delete/Trace/Options... instead
|
// This is a slow method, if you care about router-performance use the Handle/HandleFunc/Get/Post/Put/Delete/Trace/Options... instead
|
||||||
func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFunc) {
|
func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFunc) {
|
||||||
// here we need to find the registed methods and convert them to handler funcs
|
// here we need to find the registered methods and convert them to handler funcs
|
||||||
// methods are collected by method naming: Get(),GetBy(...), Post(),PostBy(...), Put() and so on
|
// methods are collected by method naming: Get(),GetBy(...), Post(),PostBy(...), Put() and so on
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
path = "/"
|
path = "/"
|
||||||
|
@ -1572,17 +1573,17 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
|
||||||
}
|
}
|
||||||
methodFuncType := methodFunc.Type()
|
methodFuncType := methodFunc.Type()
|
||||||
numInLen := methodFuncType.NumIn() // how much data we should receive from the request
|
numInLen := methodFuncType.NumIn() // how much data we should receive from the request
|
||||||
registedPath := path
|
registeredPath := path
|
||||||
|
|
||||||
for i := 1; i < numInLen; i++ { // from 1 because the first is the 'object'
|
for i := 1; i < numInLen; i++ { // from 1 because the first is the 'object'
|
||||||
if registedPath[len(registedPath)-1] == slashByte {
|
if registeredPath[len(registeredPath)-1] == slashByte {
|
||||||
registedPath += ":" + string(paramPrefix) + strconv.Itoa(i)
|
registeredPath += ":" + string(paramPrefix) + strconv.Itoa(i)
|
||||||
} else {
|
} else {
|
||||||
registedPath += "/:" + string(paramPrefix) + strconv.Itoa(i)
|
registeredPath += "/:" + string(paramPrefix) + strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func(registedPath string, typ reflect.Type, contextField reflect.StructField, methodFunc reflect.Value, paramsLen int, method string) {
|
func(registeredPath string, typ reflect.Type, contextField reflect.StructField, methodFunc reflect.Value, paramsLen int, method string) {
|
||||||
var handlersFn []HandlerFunc
|
var handlersFn []HandlerFunc
|
||||||
|
|
||||||
handlersFn = append(handlersFn, middleware...)
|
handlersFn = append(handlersFn, middleware...)
|
||||||
|
@ -1604,8 +1605,8 @@ func (api *muxAPI) API(path string, restAPI HandlerAPI, middleware ...HandlerFun
|
||||||
methodFunc.Call(args)
|
methodFunc.Call(args)
|
||||||
})
|
})
|
||||||
// register route
|
// register route
|
||||||
api.HandleFunc(method, registedPath, handlersFn...)
|
api.HandleFunc(method, registeredPath, handlersFn...)
|
||||||
}(registedPath, typ, contextField, methodFunc, numInLen-1, methodName)
|
}(registeredPath, typ, contextField, methodFunc, numInLen-1, methodName)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,8 +1660,8 @@ func Trace(path string, handlersFn ...HandlerFunc) RouteNameFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any registers a route for ALL of the http methods (Get,Post,Put,Head,Patch,Options,Connect,Delete)
|
// Any registers a route for ALL of the http methods (Get,Post,Put,Head,Patch,Options,Connect,Delete)
|
||||||
func Any(registedPath string, handlersFn ...HandlerFunc) {
|
func Any(registeredPath string, handlersFn ...HandlerFunc) {
|
||||||
Default.Any(registedPath, handlersFn...)
|
Default.Any(registeredPath, handlersFn...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1710,9 +1711,9 @@ func (api *muxAPI) Trace(path string, handlersFn ...HandlerFunc) RouteNameFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any registers a route for ALL of the http methods (Get,Post,Put,Head,Patch,Options,Connect,Delete)
|
// Any registers a route for ALL of the http methods (Get,Post,Put,Head,Patch,Options,Connect,Delete)
|
||||||
func (api *muxAPI) Any(registedPath string, handlersFn ...HandlerFunc) {
|
func (api *muxAPI) Any(registeredPath string, handlersFn ...HandlerFunc) {
|
||||||
for _, k := range AllMethods {
|
for _, k := range AllMethods {
|
||||||
api.HandleFunc(k, registedPath, handlersFn...)
|
api.HandleFunc(k, registeredPath, handlersFn...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1790,7 +1791,7 @@ func (api *muxAPI) StaticContent(reqPath string, cType string, content []byte) R
|
||||||
return api.registerResourceRoute(reqPath, h)
|
return api.registerResourceRoute(reqPath, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticEmbedded used when files are distrubuted inside the app executable, using go-bindata mostly
|
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||||
// First parameter is the request path, the path which the files in the vdir(second parameter) will be served to, for example "/static"
|
// First parameter is the request path, the path which the files in the vdir(second parameter) will be served to, for example "/static"
|
||||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||||
// Third parameter is the Asset function
|
// Third parameter is the Asset function
|
||||||
|
@ -1802,7 +1803,7 @@ func StaticEmbedded(requestPath string, vdir string, assetFn func(name string) (
|
||||||
return Default.StaticEmbedded(requestPath, vdir, assetFn, namesFn)
|
return Default.StaticEmbedded(requestPath, vdir, assetFn, namesFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticEmbedded used when files are distrubuted inside the app executable, using go-bindata mostly
|
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||||
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
||||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||||
// Third parameter is the Asset function
|
// Third parameter is the Asset function
|
||||||
|
@ -1899,7 +1900,7 @@ func (api *muxAPI) StaticEmbedded(requestPath string, vdir string, assetFn func(
|
||||||
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
||||||
// Note that you have to call it on every favicon you have to serve automatically (dekstop, mobile and so on)
|
// Note that you have to call it on every favicon you have to serve automatically (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// panics on error
|
// panics on error
|
||||||
func Favicon(favPath string, requestPath ...string) RouteNameFunc {
|
func Favicon(favPath string, requestPath ...string) RouteNameFunc {
|
||||||
|
@ -1913,7 +1914,7 @@ func Favicon(favPath string, requestPath ...string) RouteNameFunc {
|
||||||
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
// you can declare your own path if you have more than one favicon (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
// this func will add a route for you which will static serve the /yuorpath/yourfile.ico to the /yourfile.ico (nothing special that you can't handle by yourself)
|
||||||
// Note that you have to call it on every favicon you have to serve automatically (dekstop, mobile and so on)
|
// Note that you have to call it on every favicon you have to serve automatically (desktop, mobile and so on)
|
||||||
//
|
//
|
||||||
// panics on error
|
// panics on error
|
||||||
func (api *muxAPI) Favicon(favPath string, requestPath ...string) RouteNameFunc {
|
func (api *muxAPI) Favicon(favPath string, requestPath ...string) RouteNameFunc {
|
||||||
|
|
10
plugin.go
10
plugin.go
|
@ -1,5 +1,7 @@
|
||||||
package iris
|
package iris
|
||||||
|
|
||||||
|
///TODO: Be ready for go v1.8 in order to accomplish my first idea.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -13,8 +15,8 @@ var (
|
||||||
errPluginAlreadyExists = errors.New("Cannot use the same plugin again, '%s[%s]' is already exists")
|
errPluginAlreadyExists = errors.New("Cannot use the same plugin again, '%s[%s]' is already exists")
|
||||||
// errPluginActivate returns an error with message: 'While trying to activate plugin '+plugin name'. Trace: +specific error'
|
// errPluginActivate returns an error with message: 'While trying to activate plugin '+plugin name'. Trace: +specific error'
|
||||||
errPluginActivate = errors.New("While trying to activate plugin '%s'. Trace: %s")
|
errPluginActivate = errors.New("While trying to activate plugin '%s'. Trace: %s")
|
||||||
// errPluginRemoveNoPlugins returns an error with message: 'No plugins are registed yet, you cannot remove a plugin from an empty list!'
|
// errPluginRemoveNoPlugins returns an error with message: 'No plugins are registered yet, you cannot remove a plugin from an empty list!'
|
||||||
errPluginRemoveNoPlugins = errors.New("No plugins are registed yet, you cannot remove a plugin from an empty list!")
|
errPluginRemoveNoPlugins = errors.New("No plugins are registered yet, you cannot remove a plugin from an empty list!")
|
||||||
// errPluginRemoveEmptyName returns an error with message: 'Plugin with an empty name cannot be removed'
|
// errPluginRemoveEmptyName returns an error with message: 'Plugin with an empty name cannot be removed'
|
||||||
errPluginRemoveEmptyName = errors.New("Plugin with an empty name cannot be removed")
|
errPluginRemoveEmptyName = errors.New("Plugin with an empty name cannot be removed")
|
||||||
// errPluginRemoveNotFound returns an error with message: 'Cannot remove a plugin which doesn't exists'
|
// errPluginRemoveNotFound returns an error with message: 'Cannot remove a plugin which doesn't exists'
|
||||||
|
@ -248,7 +250,7 @@ func (d *pluginDownloadManager) Install(remoteFileZip string, targetDirectory st
|
||||||
return fs.Install(remoteFileZip, targetDirectory, true)
|
return fs.Install(remoteFileZip, targetDirectory, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pluginContainer is the base container of all Iris, registed plugins
|
// pluginContainer is the base container of all Iris, registered plugins
|
||||||
type pluginContainer struct {
|
type pluginContainer struct {
|
||||||
activatedPlugins []Plugin
|
activatedPlugins []Plugin
|
||||||
customEvents map[string][]func()
|
customEvents map[string][]func()
|
||||||
|
@ -379,7 +381,7 @@ func (p *pluginContainer) GetDownloader() PluginDownloadManager {
|
||||||
return p.downloader
|
return p.downloader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Printf sends plain text to any registed logger (future), some plugins maybe want use this method
|
// Printf sends plain text to any registered logger (future), some plugins maybe want use this method
|
||||||
// maybe at the future I change it, instead of sync even-driven to async channels...
|
// maybe at the future I change it, instead of sync even-driven to async channels...
|
||||||
func (p *pluginContainer) Printf(format string, a ...interface{}) {
|
func (p *pluginContainer) Printf(format string, a ...interface{}) {
|
||||||
if p.logger != nil {
|
if p.logger != nil {
|
||||||
|
|
|
@ -125,7 +125,7 @@ func (t testPluginActivationType) Activate(p iris.PluginContainer) error {
|
||||||
// if an error happened then all of them are not activated/added to the plugin container
|
// if an error happened then all of them are not activated/added to the plugin container
|
||||||
func AddPluginTo(t *testing.T, plugins iris.PluginContainer, plugin iris.Plugin, expectingCount int) {
|
func AddPluginTo(t *testing.T, plugins iris.PluginContainer, plugin iris.Plugin, expectingCount int) {
|
||||||
plugins.Add(plugin)
|
plugins.Add(plugin)
|
||||||
if plugins.Len() != expectingCount { // 2 because it registeres a second plugin also
|
if plugins.Len() != expectingCount { // 2 because it registers a second plugin also
|
||||||
t.Fatalf("Expected activated plugins to be: %d but we got: %d", expectingCount, plugins.Len())
|
t.Fatalf("Expected activated plugins to be: %d but we got: %d", expectingCount, plugins.Len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ func TestPluginEvents(t *testing.T) {
|
||||||
myplugin := &testPluginEx{}
|
myplugin := &testPluginEx{}
|
||||||
plugins.Add(myplugin)
|
plugins.Add(myplugin)
|
||||||
if plugins.Len() != 4 {
|
if plugins.Len() != 4 {
|
||||||
t.Fatalf("Expected: %d plugins to be registed but we got: %d", 4, plugins.Len())
|
t.Fatalf("Expected: %d plugins to be registered but we got: %d", 4, plugins.Len())
|
||||||
}
|
}
|
||||||
desc := plugins.GetDescription(myplugin)
|
desc := plugins.GetDescription(myplugin)
|
||||||
if desc != testPluginExDescription {
|
if desc != testPluginExDescription {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package iris_test
|
package iris_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// most tests lives inside context_test.go:Transactions, there lives the response writer's full and coblex tests
|
// most tests lives inside context_test.go:Transactions, there lives the response writer's full and coblex tests
|
||||||
|
@ -63,3 +65,35 @@ func TestResponseWriterToRecorderMiddleware(t *testing.T) {
|
||||||
|
|
||||||
e.GET("/").Expect().Status(iris.StatusForbidden).Body().Equal(beforeFlushBody)
|
e.GET("/").Expect().Status(iris.StatusForbidden).Body().Equal(beforeFlushBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleResponseWriter_WriteHeader() {
|
||||||
|
// func TestResponseWriterMultipleWriteHeader(t *testing.T) {
|
||||||
|
iris.ResetDefault()
|
||||||
|
iris.Default.Set(iris.OptionDisableBanner(true))
|
||||||
|
|
||||||
|
expectedOutput := "Hey"
|
||||||
|
iris.Get("/", func(ctx *iris.Context) {
|
||||||
|
|
||||||
|
// here
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
ctx.ResponseWriter.WriteHeader(iris.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Writef(expectedOutput)
|
||||||
|
|
||||||
|
// here
|
||||||
|
fmt.Println(expectedOutput)
|
||||||
|
|
||||||
|
// here
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
ctx.SetStatusCode(iris.StatusOK)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
e := httptest.New(iris.Default, nil)
|
||||||
|
e.GET("/").Expect().Status(iris.StatusOK).Body().Equal(expectedOutput)
|
||||||
|
// here it shouldn't log an error that status code write multiple times (by the net/http package.)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hey
|
||||||
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ func (tsf TransactionScopeFunc) EndTransaction(maybeErr TransactionErrResult, ct
|
||||||
return tsf(maybeErr, ctx)
|
return tsf(maybeErr, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransientTransactionScope explaination:
|
// TransientTransactionScope explanation:
|
||||||
//
|
//
|
||||||
// independent 'silent' scope, if transaction fails (if transaction.IsFailure() == true)
|
// independent 'silent' scope, if transaction fails (if transaction.IsFailure() == true)
|
||||||
// then its response is not written to the real context no error is provided to the user.
|
// then its response is not written to the real context no error is provided to the user.
|
||||||
|
@ -136,7 +136,7 @@ var TransientTransactionScope = TransactionScopeFunc(func(maybeErr TransactionEr
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
// RequestTransactionScope explaination:
|
// RequestTransactionScope explanation:
|
||||||
//
|
//
|
||||||
// if scope fails (if transaction.IsFailure() == true)
|
// if scope fails (if transaction.IsFailure() == true)
|
||||||
// then the rest of the context's response (transaction or normal flow)
|
// then the rest of the context's response (transaction or normal flow)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user