1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-18 10:27:06 +00:00

(#1554) Add support for all common compressions (write and read)

- Remove the context.Context interface and export the *context, the iris.Context now points to the pointer\nSupport compression and rate limiting in the FileServer\nBit of code organisation


Former-commit-id: ad1c61bf968059510c6be9e7f2cceec7da70ba17
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-07-10 23:21:09 +03:00
parent 645da2b2ef
commit 0f113dfcda
112 changed files with 2119 additions and 3390 deletions

View File

@@ -1,90 +0,0 @@
package main
// In this package I'll show you how to override the existing Context's functions and methods.
// You can easly navigate to the custom-context example to see how you can add new functions
// to your own context (need a custom handler).
//
// This way is far easier to understand and it's faster when you want to override existing methods:
import (
"reflect"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
)
// Create your own custom Context, put any fields you wanna need.
type MyContext struct {
// Optional Part 1: embed (optional but required if you don't want to override all context's methods)
iris.Context
}
var _ iris.Context = &MyContext{} // optionally: validate on compile-time if MyContext implements context.Context.
// The only one important if you will override the Context
// with an embedded context.Context inside it.
// Required in order to run the handlers via this "*MyContext".
func (ctx *MyContext) Do(handlers context.Handlers) {
context.Do(ctx, handlers)
}
// The second one important if you will override the Context
// with an embedded context.Context inside it.
// Required in order to run the chain of handlers via this "*MyContext".
func (ctx *MyContext) Next() {
context.Next(ctx)
}
// Override any context's method you want...
// [...]
func (ctx *MyContext) HTML(format string, args ...interface{}) (int, error) {
ctx.Application().Logger().Infof("Executing .HTML function from MyContext")
ctx.ContentType("text/html")
return ctx.Writef(format, args...)
}
func main() {
app := iris.New()
// app.Logger().SetLevel("debug")
// The only one Required:
// here is how you define how your own context will
// be created and acquired from the iris' generic context pool.
app.ContextPool.Attach(func() iris.Context {
return &MyContext{
// Optional Part 3:
Context: context.NewContext(app),
}
})
// Register a view engine on .html files inside the ./view/** directory.
app.RegisterView(iris.HTML("./view", ".html"))
// register your route, as you normally do
app.Handle("GET", "/", recordWhichContextJustForProofOfConcept, func(ctx iris.Context) {
// use the context's overridden HTML method.
ctx.HTML("<h1> Hello from my custom context's HTML! </h1>")
})
// this will be executed by the MyContext.Context
// if MyContext is not directly define the View function by itself.
app.Handle("GET", "/hi/{firstname:alphabetical}", recordWhichContextJustForProofOfConcept, func(ctx iris.Context) {
firstname := ctx.Params().Get("firstname")
ctx.ViewData("firstname", firstname)
ctx.Gzip(true)
ctx.View("hi.html")
})
app.Listen(":8080")
}
// should always print "($PATH) Handler is executing from 'MyContext'"
func recordWhichContextJustForProofOfConcept(ctx iris.Context) {
ctx.Application().Logger().Infof("(%s) Handler is executing from: '%s'", ctx.Path(), reflect.TypeOf(ctx).Elem().Name())
ctx.Next()
}
// Look "new-implementation" to see how you can create an entirely new Context with new functions.

View File

@@ -1 +0,0 @@
<h1> Hi {{.firstname}} </h1>

View File

@@ -1,103 +0,0 @@
package main
import (
"sync"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/sessions"
)
// Owner is our application structure, it contains the methods or fields we need,
// think it as the owner of our *Context.
type Owner struct {
// define here the fields that are global
// and shared to all clients.
sessionsManager *sessions.Sessions
}
// this package-level variable "application" will be used inside context to communicate with our global Application.
var owner = &Owner{
sessionsManager: sessions.New(sessions.Config{Cookie: "mysessioncookie"}),
}
// Context is our custom context.
// Let's implement a context which will give us access
// to the client's Session with a trivial `ctx.Session()` call.
type Context struct {
iris.Context
session *sessions.Session
}
// Session returns the current client's session.
func (ctx *Context) Session() *sessions.Session {
// this help us if we call `Session()` multiple times in the same handler
if ctx.session == nil {
// start a new session if not created before.
ctx.session = owner.sessionsManager.Start(ctx.Context)
}
return ctx.session
}
// Bold will send a bold text to the client.
func (ctx *Context) Bold(text string) {
ctx.HTML("<b>" + text + "</b>")
}
var contextPool = sync.Pool{New: func() interface{} {
return &Context{}
}}
func acquire(original iris.Context) *Context {
ctx := contextPool.Get().(*Context)
ctx.Context = original // set the context to the original one in order to have access to iris's implementation.
ctx.session = nil // reset the session
return ctx
}
func release(ctx *Context) {
contextPool.Put(ctx)
}
// Handler will convert our handler of func(*Context) to an iris Handler,
// in order to be compatible with the HTTP API.
func Handler(h func(*Context)) iris.Handler {
return func(original iris.Context) {
ctx := acquire(original)
h(ctx)
release(ctx)
}
}
func newApp() *iris.Application {
app := iris.New()
// Work as you did before, the only difference
// is that the original context.Handler should be wrapped with our custom
// `Handler` function.
app.Get("/", Handler(func(ctx *Context) {
ctx.Bold("Hello from our *Context")
}))
app.Post("/set", Handler(func(ctx *Context) {
nameFieldValue := ctx.FormValue("name")
ctx.Session().Set("name", nameFieldValue)
ctx.Writef("set session = " + nameFieldValue)
}))
app.Get("/get", Handler(func(ctx *Context) {
name := ctx.Session().GetString("name")
ctx.Writef(name)
}))
return app
}
func main() {
app := newApp()
// GET: http://localhost:8080
// POST: http://localhost:8080/set
// GET: http://localhost:8080/get
app.Listen(":8080")
}

View File

@@ -1,26 +0,0 @@
package main
import (
"testing"
"github.com/kataras/iris/v12/httptest"
)
func TestCustomContextNewImpl(t *testing.T) {
app := newApp()
e := httptest.New(t, app, httptest.URL("http://localhost:8080"))
e.GET("/").Expect().
Status(httptest.StatusOK).
ContentType("text/html").
Body().Equal("<b>Hello from our *Context</b>")
expectedName := "iris"
e.POST("/set").WithFormField("name", expectedName).Expect().
Status(httptest.StatusOK).
Body().Equal("set session = " + expectedName)
e.GET("/get").Expect().
Status(httptest.StatusOK).
Body().Equal(expectedName)
}

View File

@@ -14,7 +14,7 @@ import (
Build(provider router.RoutesProvider) error
- RouteExists reports whether a particular route exists.
RouteExists(ctx iris.Context, method, path string) bool
- FireErrorCode(ctx context.Context) should handle the given ctx.GetStatusCode().
- FireErrorCode(ctx iris.Context) should handle the given ctx.GetStatusCode().
For a more detailed, complete and useful example
you can take a look at the iris' router itself which is located at:

View File

@@ -179,7 +179,7 @@ func main() {
app.Get("/profile/{id:uint64 min(1)}/friends/{friendid:uint64 min(1) else 504}", func(ctx iris.Context) {
id := ctx.Params().GetUint64Default("id", 0)
friendid := ctx.Params().GetUint64Default("friendid", 0)
ctx.Writef("Hello id: %d looking for friend id: ", id, friendid)
ctx.Writef("Hello id: %d looking for friend id: %d", id, friendid)
}) // this will throw e 504 error code instead of 404 if all route's macros not passed.
// :uint8 0 to 255.