mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
OK, my dream-idea is implemented. TODO: Some examples and doc.go is not updated yet, comments on the mvc/di subpackage, the tutorial/vuejs-todo-mvc is running but not finished yet (it's using browser's localstorage and it should be replaced by the http requests that are registered via iris mvc
Former-commit-id: 0ea7e01ce1d78bcb78b40f3b0f5c03ad7c9abaea
This commit is contained in:
parent
55dfd195e0
commit
34664aa311
|
@ -1,19 +1,8 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import "github.com/kataras/iris/mvc"
|
|
||||||
|
|
||||||
// ValuesController is the equivalent
|
// ValuesController is the equivalent
|
||||||
// `ValuesController` of the .net core 2.0 mvc application.
|
// `ValuesController` of the .net core 2.0 mvc application.
|
||||||
type ValuesController struct {
|
type ValuesController struct{}
|
||||||
mvc.C
|
|
||||||
}
|
|
||||||
|
|
||||||
/* on windows tests(older) the Get was:
|
|
||||||
func (vc *ValuesController) Get() {
|
|
||||||
// id,_ := vc.Params.GetInt("id")
|
|
||||||
// vc.Ctx.WriteString("value")
|
|
||||||
}
|
|
||||||
but as Iris is always going better, now supports return values as well*/
|
|
||||||
|
|
||||||
// Get handles "GET" requests to "api/values/{id}".
|
// Get handles "GET" requests to "api/values/{id}".
|
||||||
func (vc *ValuesController) Get() string {
|
func (vc *ValuesController) Get() string {
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
/// TODO: remove this on the "master" branch, or even replace it
|
||||||
|
// with the "iris-mvc" (the new implementatioin is even faster, close to handlers version,
|
||||||
|
// with bindings or without).
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/kataras/iris/_benchmarks/iris-mvc2/controllers"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/_benchmarks/iris-mvc/controllers"
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
app.Controller("/api/values/{id}", new(controllers.ValuesController))
|
mvc.New(app.Party("/api/values/{id}")).Register(new(controllers.ValuesController))
|
||||||
|
|
||||||
// 24 August 2017: Iris has a built'n version updater but we don't need it
|
|
||||||
// when benchmarking...
|
|
||||||
app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker)
|
app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package controllers
|
|
||||||
|
|
||||||
// import "github.com/kataras/iris/mvc2"
|
|
||||||
|
|
||||||
// ValuesController is the equivalent
|
|
||||||
// `ValuesController` of the .net core 2.0 mvc application.
|
|
||||||
type ValuesController struct{} //{ mvc2.C }
|
|
||||||
|
|
||||||
/* on windows tests(older) the Get was:
|
|
||||||
func (vc *ValuesController) Get() {
|
|
||||||
// id,_ := vc.Params.GetInt("id")
|
|
||||||
// vc.Ctx.WriteString("value")
|
|
||||||
}
|
|
||||||
but as Iris is always going better, now supports return values as well*/
|
|
||||||
|
|
||||||
// Get handles "GET" requests to "api/values/{id}".
|
|
||||||
func (vc *ValuesController) Get() string {
|
|
||||||
return "value"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put handles "PUT" requests to "api/values/{id}".
|
|
||||||
func (vc *ValuesController) Put() {}
|
|
||||||
|
|
||||||
// Delete handles "DELETE" requests to "api/values/{id}".
|
|
||||||
func (vc *ValuesController) Delete() {}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
/// TODO: remove this on the "master" branch, or even replace it
|
|
||||||
// with the "iris-mvc" (the new implementatioin is even faster, close to handlers version,
|
|
||||||
// with bindings or without).
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kataras/iris"
|
|
||||||
"github.com/kataras/iris/_benchmarks/iris-mvc2/controllers"
|
|
||||||
"github.com/kataras/iris/mvc2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
app := iris.New()
|
|
||||||
mvc2.New().Controller(app.Party("/api/values/{id}"), new(controllers.ValuesController))
|
|
||||||
app.Run(iris.Addr(":5000"), iris.WithoutVersionChecker)
|
|
||||||
}
|
|
|
@ -1,13 +1,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/kataras/iris"
|
||||||
"github.com/kataras/iris"
|
|
||||||
"github.com/kataras/iris/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
app.Get("/api/values/{id}", func(ctx context.Context) {
|
app.Get("/api/values/{id}", func(ctx iris.Context) {
|
||||||
ctx.WriteString("value")
|
ctx.WriteString("value")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/mvc"
|
"github.com/kataras/iris/mvc"
|
||||||
// auto-completion does not working well with type aliases
|
|
||||||
// when embedded fields.
|
|
||||||
// We should complete a report on golang repo for that at some point.
|
|
||||||
//
|
|
||||||
// Therefore import the "mvc" package manually
|
|
||||||
// here at "hello-world" so users can see that
|
|
||||||
// import path somewhere else than the "FAQ" section.
|
|
||||||
|
|
||||||
"github.com/kataras/iris/middleware/logger"
|
"github.com/kataras/iris/middleware/logger"
|
||||||
"github.com/kataras/iris/middleware/recover"
|
"github.com/kataras/iris/middleware/recover"
|
||||||
|
@ -43,27 +36,18 @@ func main() {
|
||||||
app.Use(recover.New())
|
app.Use(recover.New())
|
||||||
app.Use(logger.New())
|
app.Use(logger.New())
|
||||||
|
|
||||||
app.Controller("/", new(ExampleController))
|
// Register a controller based on the root Router, "/".
|
||||||
|
mvc.New(app).Register(new(ExampleController))
|
||||||
|
|
||||||
// http://localhost:8080
|
// http://localhost:8080
|
||||||
// http://localhost:8080/ping
|
// http://localhost:8080/ping
|
||||||
// http://localhost:8080/hello
|
// http://localhost:8080/hello
|
||||||
|
// http://localhost:8080/custom_path
|
||||||
app.Run(iris.Addr(":8080"))
|
app.Run(iris.Addr(":8080"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExampleController serves the "/", "/ping" and "/hello".
|
// ExampleController serves the "/", "/ping" and "/hello".
|
||||||
type ExampleController struct {
|
type ExampleController struct{}
|
||||||
// if you build with go1.8 you have to use the mvc package always,
|
|
||||||
// otherwise
|
|
||||||
// you can, optionally
|
|
||||||
// use the type alias `iris.C`,
|
|
||||||
// same for
|
|
||||||
// context.Context -> iris.Context,
|
|
||||||
// mvc.Result -> iris.Result,
|
|
||||||
// mvc.Response -> iris.Response,
|
|
||||||
// mvc.View -> iris.View
|
|
||||||
mvc.C
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get serves
|
// Get serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
|
@ -89,6 +73,31 @@ func (c *ExampleController) GetHello() interface{} {
|
||||||
return map[string]string{"message": "Hello Iris!"}
|
return map[string]string{"message": "Hello Iris!"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BeforeActivate called once, before the controller adapted to the main application
|
||||||
|
// and of course before the server ran.
|
||||||
|
// After version 9 you can also add custom routes for a specific controller's methods.
|
||||||
|
// Here you can register custom method's handlers
|
||||||
|
// use the standard router with `ca.Router` to do something that you can do without mvc as well,
|
||||||
|
// and add dependencies that will be binded to a controller's fields or method function's input arguments.
|
||||||
|
func (c *ExampleController) BeforeActivate(ca *mvc.ControllerActivator) {
|
||||||
|
anyMiddlewareHere := func(ctx iris.Context) {
|
||||||
|
ctx.Application().Logger().Warnf("Inside /custom_path")
|
||||||
|
ctx.Next()
|
||||||
|
}
|
||||||
|
ca.Handle("GET", "/custom_path", "CustomHandlerWithoutFollowingTheNamingGuide", anyMiddlewareHere)
|
||||||
|
|
||||||
|
// or even add a global middleware based on this controller's router,
|
||||||
|
// which in this example is the root "/":
|
||||||
|
// ca.Router.Use(myMiddleware)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomHandlerWithoutFollowingTheNamingGuide serves
|
||||||
|
// Method: GET
|
||||||
|
// Resource: http://localhost:8080/custom_path
|
||||||
|
func (c *ExampleController) CustomHandlerWithoutFollowingTheNamingGuide() string {
|
||||||
|
return "hello from the custom handler without following the naming guide"
|
||||||
|
}
|
||||||
|
|
||||||
// GetUserBy serves
|
// GetUserBy serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/user/{username:string}
|
// Resource: http://localhost:8080/user/{username:string}
|
||||||
|
@ -121,4 +130,14 @@ func (c *ExampleController) Trace() {}
|
||||||
func (c *ExampleController) All() {}
|
func (c *ExampleController) All() {}
|
||||||
// OR
|
// OR
|
||||||
func (c *ExampleController) Any() {}
|
func (c *ExampleController) Any() {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func (c *ExampleController) BeforeActivate(ca *mvc.ControllerActivator) {
|
||||||
|
// 1 -> the HTTP Method
|
||||||
|
// 2 -> the route's path
|
||||||
|
// 3 -> this controller's method name that should be handler for that route.
|
||||||
|
ca.Handle("GET", "/mypath/{param}", "DoIt", optionalMiddlewareHere...)
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,38 +10,52 @@ import (
|
||||||
"github.com/kataras/iris/_examples/mvc/overview/web/middleware"
|
"github.com/kataras/iris/_examples/mvc/overview/web/middleware"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
app.Logger().SetLevel("debug")
|
||||||
|
|
||||||
// Load the template files.
|
// Load the template files.
|
||||||
app.RegisterView(iris.HTML("./web/views", ".html"))
|
app.RegisterView(iris.HTML("./web/views", ".html"))
|
||||||
|
|
||||||
// Register our controllers.
|
// Register our controllers.
|
||||||
app.Controller("/hello", new(controllers.HelloController))
|
mvc.New(app.Party("/hello")).Register(new(controllers.HelloController))
|
||||||
|
// You can also split the code you write to configure an mvc.Application
|
||||||
|
// using the `Configure` method, as shown below.
|
||||||
|
mvc.New(app.Party("/movies")).Configure(movies)
|
||||||
|
|
||||||
// Create our movie repository with some (memory) data from the datasource.
|
|
||||||
repo := repositories.NewMovieRepository(datasource.Movies)
|
|
||||||
// Create our movie service, we will bind it to the movie controller.
|
|
||||||
movieService := services.NewMovieService(repo)
|
|
||||||
|
|
||||||
app.Controller("/movies", new(controllers.MovieController),
|
|
||||||
// Bind the "movieService" to the MovieController's Service (interface) field.
|
|
||||||
movieService,
|
|
||||||
// Add the basic authentication(admin:password) middleware
|
|
||||||
// for the /movies based requests.
|
|
||||||
middleware.BasicAuth)
|
|
||||||
|
|
||||||
// Start the web server at localhost:8080
|
|
||||||
// http://localhost:8080/hello
|
// http://localhost:8080/hello
|
||||||
// http://localhost:8080/hello/iris
|
// http://localhost:8080/hello/iris
|
||||||
// http://localhost:8080/movies
|
// http://localhost:8080/movies
|
||||||
// http://localhost:8080/movies/1
|
// http://localhost:8080/movies/1
|
||||||
app.Run(
|
app.Run(
|
||||||
|
// Start the web server at localhost:8080
|
||||||
iris.Addr("localhost:8080"),
|
iris.Addr("localhost:8080"),
|
||||||
|
// disables updates:
|
||||||
iris.WithoutVersionChecker,
|
iris.WithoutVersionChecker,
|
||||||
|
// skip err server closed when CTRL/CMD+C pressed:
|
||||||
iris.WithoutServerError(iris.ErrServerClosed),
|
iris.WithoutServerError(iris.ErrServerClosed),
|
||||||
iris.WithOptimizations, // enables faster json serialization and more
|
// enables faster json serialization and more:
|
||||||
|
iris.WithOptimizations,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note the mvc.Application, it's not iris.Application.
|
||||||
|
func movies(app *mvc.Application) {
|
||||||
|
// Add the basic authentication(admin:password) middleware
|
||||||
|
// for the /movies based requests.
|
||||||
|
app.Router.Use(middleware.BasicAuth)
|
||||||
|
|
||||||
|
// Create our movie repository with some (memory) data from the datasource.
|
||||||
|
repo := repositories.NewMovieRepository(datasource.Movies)
|
||||||
|
// Create our movie service, we will bind it to the movie app's dependencies.
|
||||||
|
movieService := services.NewMovieService(repo)
|
||||||
|
app.AddDependencies(movieService)
|
||||||
|
|
||||||
|
// Register our movies controller.
|
||||||
|
// Note that you can register more than one controller
|
||||||
|
// you can alos create child mvc apps using the `movies.NewChild()` if you want.
|
||||||
|
app.Register(new(controllers.MovieController))
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,7 @@ import (
|
||||||
|
|
||||||
// HelloController is our sample controller
|
// HelloController is our sample controller
|
||||||
// it handles GET: /hello and GET: /hello/{name}
|
// it handles GET: /hello and GET: /hello/{name}
|
||||||
type HelloController struct {
|
type HelloController struct{}
|
||||||
mvc.C
|
|
||||||
}
|
|
||||||
|
|
||||||
var helloView = mvc.View{
|
var helloView = mvc.View{
|
||||||
Name: "hello/index.html",
|
Name: "hello/index.html",
|
||||||
|
@ -32,7 +30,7 @@ func (c *HelloController) Get() mvc.Result {
|
||||||
return helloView
|
return helloView
|
||||||
}
|
}
|
||||||
|
|
||||||
// you can define a standard error in order to be re-usable anywhere in your app.
|
// you can define a standard error in order to re-use anywhere in your app.
|
||||||
var errBadName = errors.New("bad name")
|
var errBadName = errors.New("bad name")
|
||||||
|
|
||||||
// you can just return it as error or even better
|
// you can just return it as error or even better
|
||||||
|
|
|
@ -9,17 +9,10 @@ import (
|
||||||
"github.com/kataras/iris/_examples/mvc/overview/services"
|
"github.com/kataras/iris/_examples/mvc/overview/services"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/mvc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MovieController is our /movies controller.
|
// MovieController is our /movies controller.
|
||||||
type MovieController struct {
|
type MovieController struct {
|
||||||
// mvc.C is just a lightweight lightweight alternative
|
|
||||||
// to the "mvc.Controller" controller type,
|
|
||||||
// use it when you don't need mvc.Controller's fields
|
|
||||||
// (you don't need those fields when you return values from the method functions).
|
|
||||||
mvc.C
|
|
||||||
|
|
||||||
// Our MovieService, it's an interface which
|
// Our MovieService, it's an interface which
|
||||||
// is binded from the main application.
|
// is binded from the main application.
|
||||||
Service services.MovieService
|
Service services.MovieService
|
||||||
|
@ -53,9 +46,9 @@ func (c *MovieController) GetBy(id int64) (movie datamodels.Movie, found bool) {
|
||||||
// PutBy updates a movie.
|
// PutBy updates a movie.
|
||||||
// Demo:
|
// Demo:
|
||||||
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
|
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
|
||||||
func (c *MovieController) PutBy(id int64) (datamodels.Movie, error) {
|
func (c *MovieController) PutBy(ctx iris.Context, id int64) (datamodels.Movie, error) {
|
||||||
// get the request data for poster and genre
|
// get the request data for poster and genre
|
||||||
file, info, err := c.Ctx.FormFile("poster")
|
file, info, err := ctx.FormFile("poster")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return datamodels.Movie{}, errors.New("failed due form file 'poster' missing")
|
return datamodels.Movie{}, errors.New("failed due form file 'poster' missing")
|
||||||
}
|
}
|
||||||
|
@ -64,7 +57,7 @@ func (c *MovieController) PutBy(id int64) (datamodels.Movie, error) {
|
||||||
|
|
||||||
// imagine that is the url of the uploaded file...
|
// imagine that is the url of the uploaded file...
|
||||||
poster := info.Filename
|
poster := info.Filename
|
||||||
genre := c.Ctx.FormValue("genre")
|
genre := ctx.FormValue("genre")
|
||||||
|
|
||||||
return c.Service.UpdatePosterAndGenreByID(id, poster, genre)
|
return c.Service.UpdatePosterAndGenreByID(id, poster, genre)
|
||||||
}
|
}
|
||||||
|
|
1
_examples/tutorial/vuejs-todo-mvc/README.md
Normal file
1
_examples/tutorial/vuejs-todo-mvc/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Unfinished - wait until today :)
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"github.com/kataras/iris/_examples/tutorial/vuejs-todo-mvc/src/todo"
|
"github.com/kataras/iris/_examples/tutorial/vuejs-todo-mvc/src/todo"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
mvc "github.com/kataras/iris/mvc2"
|
|
||||||
"github.com/kataras/iris/sessions"
|
"github.com/kataras/iris/sessions"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TodoController is our TODO app's web controller.
|
// TodoController is our TODO app's web controller.
|
||||||
|
@ -38,10 +39,6 @@ func (c *TodoController) BeforeActivate(ca *mvc.ControllerActivator) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// ca.Router.Use(...).Done(...).Layout(...)
|
// ca.Router.Use(...).Done(...).Layout(...)
|
||||||
// TODO:(?)
|
|
||||||
// m := ca.Method("PutCompleteBy")
|
|
||||||
// m.Route.Use(...).Done(...) <- we don't have the route here but I can find something to solve this.
|
|
||||||
// m.Dependencies.Add(...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get handles the GET: /todo route.
|
// Get handles the GET: /todo route.
|
||||||
|
|
|
@ -5,8 +5,9 @@ import (
|
||||||
"github.com/kataras/iris/_examples/tutorial/vuejs-todo-mvc/src/web/controllers"
|
"github.com/kataras/iris/_examples/tutorial/vuejs-todo-mvc/src/web/controllers"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
mvc "github.com/kataras/iris/mvc2"
|
|
||||||
"github.com/kataras/iris/sessions"
|
"github.com/kataras/iris/sessions"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -22,14 +23,16 @@ func main() {
|
||||||
Cookie: "_iris_session",
|
Cookie: "_iris_session",
|
||||||
})
|
})
|
||||||
|
|
||||||
m := mvc.New()
|
m := mvc.New(app.Party("/todo"))
|
||||||
|
|
||||||
// any bindings here...
|
// any dependencies bindings here...
|
||||||
m.Bind(mvc.Session(sess))
|
m.AddDependencies(
|
||||||
|
mvc.Session(sess),
|
||||||
|
new(todo.MemoryService),
|
||||||
|
)
|
||||||
|
|
||||||
m.Bind(new(todo.MemoryService))
|
|
||||||
// controllers registration here...
|
// controllers registration here...
|
||||||
m.Controller(app.Party("/todo"), new(controllers.TodoController))
|
m.Register(new(controllers.TodoController))
|
||||||
|
|
||||||
// start the web server at http://localhost:8080
|
// start the web server at http://localhost:8080
|
||||||
app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker, iris.WithOptimizations)
|
app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker, iris.WithOptimizations)
|
||||||
|
|
4
mvc/AUTHORS
Normal file
4
mvc/AUTHORS
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# This is the official list of Iris MVC authors for copyright
|
||||||
|
# purposes.
|
||||||
|
|
||||||
|
Gerasimos Maropoulos <kataras2006@hotmail.com>
|
27
mvc/LICENSE
Normal file
27
mvc/LICENSE
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2018 Gerasimos Maropoulos. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Iris nor the names of its
|
||||||
|
contributor, Gerasimos Maropoulos, may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,78 +1,25 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kataras/iris/mvc2/di"
|
"github.com/kataras/iris/mvc/di"
|
||||||
|
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/core/router"
|
"github.com/kataras/iris/core/router"
|
||||||
"github.com/kataras/iris/core/router/macro"
|
"github.com/kataras/iris/core/router/macro"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseController is the controller interface,
|
// BaseController is the optional controller interface, if it's
|
||||||
// which the main request `C` will implement automatically.
|
// completed by the end controller then the BeginRequest and EndRequest
|
||||||
// End-dev doesn't need to have any knowledge of this if she/he doesn't want to implement
|
// are called between the controller's method responsible for the incoming request.
|
||||||
// a new Controller type.
|
|
||||||
// Controller looks the whole flow as one handler, so `ctx.Next`
|
|
||||||
// inside `BeginRequest` is not be respected.
|
|
||||||
// Alternative way to check if a middleware was procceed successfully
|
|
||||||
// and called its `ctx.Next` is the `ctx.Proceed(handler) bool`.
|
|
||||||
// You have to navigate to the `context/context#Proceed` function's documentation.
|
|
||||||
type BaseController interface {
|
type BaseController interface {
|
||||||
BeginRequest(context.Context)
|
BeginRequest(context.Context)
|
||||||
EndRequest(context.Context)
|
EndRequest(context.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// C is the basic BaseController type that can be used as an embedded anonymous field
|
|
||||||
// to custom end-dev controllers.
|
|
||||||
//
|
|
||||||
// func(c *ExampleController) Get() string |
|
|
||||||
// (string, string) |
|
|
||||||
// (string, int) |
|
|
||||||
// int |
|
|
||||||
// (int, string |
|
|
||||||
// (string, error) |
|
|
||||||
// bool |
|
|
||||||
// (any, bool) |
|
|
||||||
// error |
|
|
||||||
// (int, error) |
|
|
||||||
// (customStruct, error) |
|
|
||||||
// customStruct |
|
|
||||||
// (customStruct, int) |
|
|
||||||
// (customStruct, string) |
|
|
||||||
// Result or (Result, error)
|
|
||||||
// where Get is an HTTP Method func.
|
|
||||||
//
|
|
||||||
// Look `core/router#APIBuilder#Controller` method too.
|
|
||||||
//
|
|
||||||
// It completes the `activator.BaseController` interface.
|
|
||||||
//
|
|
||||||
// Example at: https://github.com/kataras/iris/tree/master/_examples/mvc/overview/web/controllers.
|
|
||||||
// Example usage at: https://github.com/kataras/iris/blob/master/mvc/method_result_test.go#L17.
|
|
||||||
type C struct {
|
|
||||||
// The current context.Context.
|
|
||||||
//
|
|
||||||
// we have to name it for two reasons:
|
|
||||||
// 1: can't ignore these via reflection, it doesn't give an option to
|
|
||||||
// see if the functions is derived from another type.
|
|
||||||
// 2: end-developer may want to use some method functions
|
|
||||||
// or any fields that could be conflict with the context's.
|
|
||||||
Ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ BaseController = &C{}
|
|
||||||
|
|
||||||
// BeginRequest does nothing anymore, is here to complet ethe `BaseController` interface.
|
|
||||||
// BaseController is not required anymore, `Ctx` is binded automatically by the engine's
|
|
||||||
// wrapped Handler.
|
|
||||||
func (c *C) BeginRequest(ctx context.Context) {}
|
|
||||||
|
|
||||||
// EndRequest does nothing, is here to complete the `BaseController` interface.
|
|
||||||
func (c *C) EndRequest(ctx context.Context) {}
|
|
||||||
|
|
||||||
// ControllerActivator returns a new controller type info description.
|
// ControllerActivator returns a new controller type info description.
|
||||||
// Its functionality can be overriden by the end-dev.
|
// Its functionality can be overriden by the end-dev.
|
||||||
type ControllerActivator struct {
|
type ControllerActivator struct {
|
||||||
|
@ -244,7 +191,10 @@ func (c *ControllerActivator) Handle(method, path, funcName string, middleware .
|
||||||
// get the function's input arguments' bindings.
|
// get the function's input arguments' bindings.
|
||||||
funcDependencies := c.Dependencies.Clone()
|
funcDependencies := c.Dependencies.Clone()
|
||||||
funcDependencies.AddValue(pathParams...)
|
funcDependencies.AddValue(pathParams...)
|
||||||
|
|
||||||
|
// fmt.Printf("for %s | values: %s\n", funcName, funcDependencies.Values)
|
||||||
funcInjector := funcDependencies.Func(m.Func)
|
funcInjector := funcDependencies.Func(m.Func)
|
||||||
|
// fmt.Printf("actual injector's inputs length: %d\n", funcInjector.Length)
|
||||||
|
|
||||||
// the element value, not the pointer, wil lbe used to create a
|
// the element value, not the pointer, wil lbe used to create a
|
||||||
// new controller on each incoming request.
|
// new controller on each incoming request.
|
|
@ -1,29 +1,22 @@
|
||||||
package mvc2_test
|
package mvc_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
. "github.com/kataras/iris/mvc2"
|
|
||||||
|
. "github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testControllerHandle struct {
|
type testControllerHandle struct {
|
||||||
C
|
Ctx context.Context
|
||||||
Service TestService
|
Service TestService
|
||||||
|
|
||||||
reqField string
|
reqField string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerHandle) Get() string {
|
|
||||||
return "index"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *testControllerHandle) BeginRequest(ctx iris.Context) {
|
|
||||||
c.C.BeginRequest(ctx)
|
|
||||||
c.reqField = ctx.URLParam("reqfield")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *testControllerHandle) BeforeActivate(ca *ControllerActivator) { // BeforeActivate(t *mvc.TController) {
|
func (c *testControllerHandle) BeforeActivate(ca *ControllerActivator) { // BeforeActivate(t *mvc.TController) {
|
||||||
ca.Handle("GET", "/histatic", "HiStatic")
|
ca.Handle("GET", "/histatic", "HiStatic")
|
||||||
ca.Handle("GET", "/hiservice", "HiService")
|
ca.Handle("GET", "/hiservice", "HiService")
|
||||||
|
@ -31,6 +24,16 @@ func (c *testControllerHandle) BeforeActivate(ca *ControllerActivator) { // Befo
|
||||||
ca.Handle("GET", "/hiparamempyinput/{ps:string}", "HiParamEmptyInputBy")
|
ca.Handle("GET", "/hiparamempyinput/{ps:string}", "HiParamEmptyInputBy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *testControllerHandle) BeginRequest(ctx iris.Context) {
|
||||||
|
c.reqField = ctx.URLParam("reqfield")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testControllerHandle) EndRequest(ctx iris.Context) {}
|
||||||
|
|
||||||
|
func (c *testControllerHandle) Get() string {
|
||||||
|
return "index"
|
||||||
|
}
|
||||||
|
|
||||||
func (c *testControllerHandle) HiStatic() string {
|
func (c *testControllerHandle) HiStatic() string {
|
||||||
return c.reqField
|
return c.reqField
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -96,20 +96,31 @@ func (l *methodLexer) peekPrev() (w string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var posWords = map[int]string{
|
var posWords = map[int]string{
|
||||||
0: "",
|
0: "",
|
||||||
1: "first",
|
1: "first",
|
||||||
2: "second",
|
2: "second",
|
||||||
3: "third",
|
3: "third",
|
||||||
4: "forth",
|
4: "forth",
|
||||||
5: "five",
|
5: "five",
|
||||||
6: "sixth",
|
6: "sixth",
|
||||||
7: "seventh",
|
7: "seventh",
|
||||||
8: "eighth",
|
8: "eighth",
|
||||||
9: "ninth",
|
9: "ninth",
|
||||||
|
10: "tenth",
|
||||||
|
11: "eleventh",
|
||||||
|
12: "twelfth",
|
||||||
|
13: "thirteenth",
|
||||||
|
14: "fourteenth",
|
||||||
|
15: "fifteenth",
|
||||||
|
16: "sixteenth",
|
||||||
|
17: "seventeenth",
|
||||||
|
18: "eighteenth",
|
||||||
|
19: "nineteenth",
|
||||||
|
20: "twentieth",
|
||||||
}
|
}
|
||||||
|
|
||||||
func genParamKey(argIdx int) string {
|
func genParamKey(argIdx int) string {
|
||||||
return "param" + posWords[argIdx] // paramfirst, paramsecond...
|
return "arg" + posWords[argIdx] // argfirst, argsecond...
|
||||||
}
|
}
|
||||||
|
|
||||||
type methodParser struct {
|
type methodParser struct {
|
||||||
|
@ -176,7 +187,7 @@ func (p *methodParser) parse() (method, path string, err error) {
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if path, err = p.parsePathParam(path, w, funcArgPos); err != nil {
|
if path, funcArgPos, err = p.parsePathParam(path, w, funcArgPos); err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,24 +195,22 @@ func (p *methodParser) parse() (method, path string, err error) {
|
||||||
}
|
}
|
||||||
// static path.
|
// static path.
|
||||||
path += "/" + strings.ToLower(w)
|
path += "/" + strings.ToLower(w)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *methodParser) parsePathParam(path string, w string, funcArgPos int) (string, error) {
|
func (p *methodParser) parsePathParam(path string, w string, funcArgPos int) (string, int, error) {
|
||||||
typ := p.fn.Type
|
typ := p.fn.Type
|
||||||
|
|
||||||
if typ.NumIn() <= funcArgPos {
|
if typ.NumIn() <= funcArgPos {
|
||||||
|
|
||||||
// By found but input arguments are not there, so act like /by path without restricts.
|
// By found but input arguments are not there, so act like /by path without restricts.
|
||||||
path += "/" + strings.ToLower(w)
|
path += "/" + strings.ToLower(w)
|
||||||
return path, nil
|
return path, funcArgPos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
paramKey = genParamKey(funcArgPos) // paramfirst, paramsecond...
|
paramKey = genParamKey(funcArgPos) // argfirst, argsecond...
|
||||||
paramType = ast.ParamTypeString // default string
|
paramType = ast.ParamTypeString // default string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -216,10 +225,19 @@ func (p *methodParser) parsePathParam(path string, w string, funcArgPos int) (st
|
||||||
// it's not wildcard, so check base on our available macro types.
|
// it's not wildcard, so check base on our available macro types.
|
||||||
paramType = pType
|
paramType = pType
|
||||||
} else {
|
} else {
|
||||||
return "", errors.New("invalid syntax for " + p.fn.Name)
|
if typ.NumIn() > funcArgPos {
|
||||||
|
// has more input arguments but we are not in the correct
|
||||||
|
// index now, maybe the first argument was an `iris/context.Context`
|
||||||
|
// so retry with the "funcArgPos" incremented.
|
||||||
|
//
|
||||||
|
// the "funcArgPos" will be updated to the caller as well
|
||||||
|
// because we return it as well.
|
||||||
|
return p.parsePathParam(path, w, funcArgPos+1)
|
||||||
|
}
|
||||||
|
return "", 0, errors.New("invalid syntax for " + p.fn.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// /{paramfirst:path}, /{paramfirst:long}...
|
// /{argfirst:path}, /{argfirst:long}...
|
||||||
path += fmt.Sprintf("/{%s:%s}", paramKey, paramType.String())
|
path += fmt.Sprintf("/{%s:%s}", paramKey, paramType.String())
|
||||||
|
|
||||||
if nextWord == "" && typ.NumIn() > funcArgPos+1 {
|
if nextWord == "" && typ.NumIn() > funcArgPos+1 {
|
||||||
|
@ -232,5 +250,5 @@ func (p *methodParser) parsePathParam(path string, w string, funcArgPos int) (st
|
||||||
return p.parsePathParam(path, nextWord, funcArgPos+1)
|
return p.parsePathParam(path, nextWord, funcArgPos+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return path, nil
|
return path, funcArgPos, nil
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// black-box testing
|
// black-box testing
|
||||||
package mvc2_test
|
package mvc_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -8,56 +8,57 @@ import (
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/core/router"
|
"github.com/kataras/iris/core/router"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
. "github.com/kataras/iris/mvc2"
|
|
||||||
|
. "github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testController struct {
|
type testController struct {
|
||||||
C
|
Ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
var writeMethod = func(c C) {
|
var writeMethod = func(ctx context.Context) {
|
||||||
c.Ctx.Writef(c.Ctx.Method())
|
ctx.Writef(ctx.Method())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testController) Get() {
|
func (c *testController) Get() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Post() {
|
func (c *testController) Post() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Put() {
|
func (c *testController) Put() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Delete() {
|
func (c *testController) Delete() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Connect() {
|
func (c *testController) Connect() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Head() {
|
func (c *testController) Head() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Patch() {
|
func (c *testController) Patch() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Options() {
|
func (c *testController) Options() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
func (c *testController) Trace() {
|
func (c *testController) Trace() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
testControllerAll struct{ C }
|
testControllerAll struct{ Ctx context.Context }
|
||||||
testControllerAny struct{ C } // exactly the same as All.
|
testControllerAny struct{ Ctx context.Context } // exactly the same as All.
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *testControllerAll) All() {
|
func (c *testControllerAll) All() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerAny) Any() {
|
func (c *testControllerAny) Any() {
|
||||||
writeMethod(c.C)
|
writeMethod(c.Ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControllerMethodFuncs(t *testing.T) {
|
func TestControllerMethodFuncs(t *testing.T) {
|
||||||
|
@ -83,7 +84,7 @@ func TestControllerMethodFuncs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerBeginAndEndRequestFunc struct {
|
type testControllerBeginAndEndRequestFunc struct {
|
||||||
C
|
Ctx context.Context
|
||||||
|
|
||||||
Username string
|
Username string
|
||||||
}
|
}
|
||||||
|
@ -93,14 +94,12 @@ type testControllerBeginAndEndRequestFunc struct {
|
||||||
// useful when more than one methods using the
|
// useful when more than one methods using the
|
||||||
// same request values or context's function calls.
|
// same request values or context's function calls.
|
||||||
func (c *testControllerBeginAndEndRequestFunc) BeginRequest(ctx context.Context) {
|
func (c *testControllerBeginAndEndRequestFunc) BeginRequest(ctx context.Context) {
|
||||||
c.C.BeginRequest(ctx)
|
|
||||||
c.Username = ctx.Params().Get("username")
|
c.Username = ctx.Params().Get("username")
|
||||||
}
|
}
|
||||||
|
|
||||||
// called after every method (Get() or Post()).
|
// called after every method (Get() or Post()).
|
||||||
func (c *testControllerBeginAndEndRequestFunc) EndRequest(ctx context.Context) {
|
func (c *testControllerBeginAndEndRequestFunc) EndRequest(ctx context.Context) {
|
||||||
ctx.Writef("done") // append "done" to the response
|
ctx.Writef("done") // append "done" to the response
|
||||||
c.C.EndRequest(ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerBeginAndEndRequestFunc) Get() {
|
func (c *testControllerBeginAndEndRequestFunc) Get() {
|
||||||
|
@ -187,7 +186,7 @@ type Model struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerEndRequestAwareness struct {
|
type testControllerEndRequestAwareness struct {
|
||||||
C
|
Ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerEndRequestAwareness) Get() {
|
func (c *testControllerEndRequestAwareness) Get() {
|
||||||
|
@ -223,9 +222,9 @@ func writeModels(ctx context.Context, names ...string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *testControllerEndRequestAwareness) BeginRequest(ctx context.Context) {}
|
||||||
func (c *testControllerEndRequestAwareness) EndRequest(ctx context.Context) {
|
func (c *testControllerEndRequestAwareness) EndRequest(ctx context.Context) {
|
||||||
writeModels(ctx, "TestModel", "myModel")
|
writeModels(ctx, "TestModel", "myModel")
|
||||||
c.C.EndRequest(ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControllerEndRequestAwareness(t *testing.T) {
|
func TestControllerEndRequestAwareness(t *testing.T) {
|
||||||
|
@ -249,7 +248,8 @@ type testBindType struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerBindStruct struct {
|
type testControllerBindStruct struct {
|
||||||
C
|
Ctx context.Context
|
||||||
|
|
||||||
// should start with upper letter of course
|
// should start with upper letter of course
|
||||||
TitlePointer *testBindType // should have the value of the "myTitlePtr" on test
|
TitlePointer *testBindType // should have the value of the "myTitlePtr" on test
|
||||||
TitleValue testBindType // should have the value of the "myTitleV" on test
|
TitleValue testBindType // should have the value of the "myTitleV" on test
|
||||||
|
@ -320,6 +320,8 @@ func (c *testCtrl0) EndRequest(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCtrl00 struct {
|
type testCtrl00 struct {
|
||||||
|
Ctx context.Context
|
||||||
|
|
||||||
testCtrl000
|
testCtrl000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,9 +332,9 @@ type testCtrl000 struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCtrl0000 struct {
|
type testCtrl0000 struct {
|
||||||
C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *testCtrl0000) BeginRequest(ctx context.Context) {}
|
||||||
func (c *testCtrl0000) EndRequest(ctx context.Context) {
|
func (c *testCtrl0000) EndRequest(ctx context.Context) {
|
||||||
ctx.Writef("finish")
|
ctx.Writef("finish")
|
||||||
}
|
}
|
||||||
|
@ -354,11 +356,11 @@ func TestControllerInsideControllerRecursively(t *testing.T) {
|
||||||
Status(iris.StatusOK).Body().Equal(expected)
|
Status(iris.StatusOK).Body().Equal(expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerRelPathFromFunc struct{ C }
|
type testControllerRelPathFromFunc struct{}
|
||||||
|
|
||||||
|
func (c *testControllerRelPathFromFunc) BeginRequest(ctx context.Context) {}
|
||||||
func (c *testControllerRelPathFromFunc) EndRequest(ctx context.Context) {
|
func (c *testControllerRelPathFromFunc) EndRequest(ctx context.Context) {
|
||||||
ctx.Writef("%s:%s", ctx.Method(), ctx.Path())
|
ctx.Writef("%s:%s", ctx.Method(), ctx.Path())
|
||||||
c.C.EndRequest(ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerRelPathFromFunc) Get() {}
|
func (c *testControllerRelPathFromFunc) Get() {}
|
||||||
|
@ -416,8 +418,6 @@ func TestControllerRelPathFromFunc(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerActivateListener struct {
|
type testControllerActivateListener struct {
|
||||||
C
|
|
||||||
|
|
||||||
TitlePointer *testBindType
|
TitlePointer *testBindType
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import "reflect"
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
targetFuncInput struct {
|
targetFuncInput struct {
|
||||||
|
@ -50,7 +48,6 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, v
|
||||||
InputIndex: i,
|
InputIndex: i,
|
||||||
Object: b,
|
Object: b,
|
||||||
})
|
})
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +66,7 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, v
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.IsAssignable(inTyp) {
|
if b.IsAssignable(inTyp) {
|
||||||
|
// println(inTyp.String() + " is assignable to " + val.Type().String())
|
||||||
// fmt.Printf("binded input index: %d for type: %s and value: %v with pointer: %v\n",
|
// fmt.Printf("binded input index: %d for type: %s and value: %v with pointer: %v\n",
|
||||||
// i, b.Type.String(), val.String(), val.Pointer())
|
// i, b.Type.String(), val.String(), val.Pointer())
|
||||||
s.inputs = append(s.inputs, &targetFuncInput{
|
s.inputs = append(s.inputs, &targetFuncInput{
|
||||||
|
@ -82,8 +80,9 @@ func MakeFuncInjector(fn reflect.Value, hijack Hijacker, goodFunc TypeChecker, v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Length = n
|
// s.Length = n
|
||||||
s.Valid = len(s.inputs) > 0
|
s.Length = len(s.inputs)
|
||||||
|
s.Valid = s.Length > 0
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import "reflect"
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Values []reflect.Value
|
type Values []reflect.Value
|
||||||
|
|
105
mvc/engine.go
Normal file
105
mvc/engine.go
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package mvc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/golog"
|
||||||
|
"github.com/kataras/iris/mvc/di"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
|
"github.com/kataras/iris/core/router"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Engine contains the Dependencies which will be binded
|
||||||
|
// to the controller(s) or handler(s) that can be created
|
||||||
|
// using the Engine's `Handler` and `Controller` methods.
|
||||||
|
//
|
||||||
|
// This is not exported for being used by everyone, use it only when you want
|
||||||
|
// to share engines between multi mvc.go#Application
|
||||||
|
// or make custom mvc handlers that can be used on the standard
|
||||||
|
// iris' APIBuilder. The last one reason is the most useful here,
|
||||||
|
// although end-devs can use the `MakeHandler` as well.
|
||||||
|
//
|
||||||
|
// For a more high-level structure please take a look at the "mvc.go#Application".
|
||||||
|
type Engine struct {
|
||||||
|
Dependencies *di.D
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEngine returns a new engine, a container for dependencies and a factory
|
||||||
|
// for handlers and controllers, this is used internally by the `mvc#Application` structure.
|
||||||
|
// Please take a look at the structure's documentation for more information.
|
||||||
|
func NewEngine() *Engine {
|
||||||
|
return &Engine{
|
||||||
|
Dependencies: di.New().Hijack(hijacker).GoodFunc(typeChecker),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone creates and returns a new engine with the parent's(current) Dependencies.
|
||||||
|
// It copies the current "e" dependencies and returns a new engine.
|
||||||
|
func (e *Engine) Clone() *Engine {
|
||||||
|
child := NewEngine()
|
||||||
|
child.Dependencies = e.Dependencies.Clone()
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler accepts a "handler" function which can accept any input arguments that match
|
||||||
|
// with the Engine's `Dependencies` and any output result; like string, int (string,int),
|
||||||
|
// custom structs, Result(View | Response) and anything you already know that mvc implementation supports.
|
||||||
|
// It returns a standard `iris/context.Handler` which can be used anywhere in an Iris Application,
|
||||||
|
// as middleware or as simple route handler or subdomain's handler.
|
||||||
|
func (e *Engine) Handler(handler interface{}) context.Handler {
|
||||||
|
h, err := MakeHandler(handler, e.Dependencies.Values...)
|
||||||
|
if err != nil {
|
||||||
|
golog.Errorf("mvc handler: %v", err)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller accepts a sub router and registers any custom struct
|
||||||
|
// as controller, if struct doesn't have any compatible methods
|
||||||
|
// neither are registered via `ControllerActivator`'s `Handle` method
|
||||||
|
// then the controller is not registered at all.
|
||||||
|
//
|
||||||
|
// A Controller may have one or more methods
|
||||||
|
// that are wrapped to a handler and registered as routes before the server ran.
|
||||||
|
// The controller's method can accept any input argument that are previously binded
|
||||||
|
// via the dependencies or route's path accepts dynamic path parameters.
|
||||||
|
// The controller's fields are also bindable via the dependencies, either a
|
||||||
|
// static value (service) or a function (dynamically) which accepts a context
|
||||||
|
// and returns a single value (this type is being used to find the relative field or method's input argument).
|
||||||
|
//
|
||||||
|
// func(c *ExampleController) Get() string |
|
||||||
|
// (string, string) |
|
||||||
|
// (string, int) |
|
||||||
|
// int |
|
||||||
|
// (int, string |
|
||||||
|
// (string, error) |
|
||||||
|
// bool |
|
||||||
|
// (any, bool) |
|
||||||
|
// error |
|
||||||
|
// (int, error) |
|
||||||
|
// (customStruct, error) |
|
||||||
|
// customStruct |
|
||||||
|
// (customStruct, int) |
|
||||||
|
// (customStruct, string) |
|
||||||
|
// Result or (Result, error)
|
||||||
|
// where Get is an HTTP Method func.
|
||||||
|
//
|
||||||
|
// Examples at: https://github.com/kataras/iris/tree/master/_examples/mvc.
|
||||||
|
func (e *Engine) Controller(router router.Party, controller interface{}, beforeActivate ...func(*ControllerActivator)) {
|
||||||
|
ca := newControllerActivator(router, controller, e.Dependencies)
|
||||||
|
|
||||||
|
// give a priority to the "beforeActivate"
|
||||||
|
// callbacks, if any.
|
||||||
|
for _, cb := range beforeActivate {
|
||||||
|
cb(ca)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if controller has an "BeforeActivate" function
|
||||||
|
// which accepts the controller activator and call it.
|
||||||
|
if activateListener, ok := controller.(interface {
|
||||||
|
BeforeActivate(*ControllerActivator)
|
||||||
|
}); ok {
|
||||||
|
activateListener.BeforeActivate(ca)
|
||||||
|
}
|
||||||
|
|
||||||
|
ca.activate()
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package mvc2_test
|
package mvc_test
|
||||||
|
|
||||||
// black-box in combination with the handler_test
|
// black-box in combination with the handler_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/kataras/iris/mvc2"
|
. "github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMvcEngineInAndHandler(t *testing.T) {
|
func TestMvcEngineInAndHandler(t *testing.T) {
|
|
@ -1,11 +1,11 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fatih/structs"
|
"github.com/fatih/structs"
|
||||||
"github.com/kataras/iris/mvc2/di"
|
"github.com/kataras/iris/mvc/di"
|
||||||
|
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
)
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2_test
|
package mvc_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -7,14 +7,15 @@ import (
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
. "github.com/kataras/iris/mvc2"
|
|
||||||
|
. "github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// activator/methodfunc/func_caller.go.
|
// activator/methodfunc/func_caller.go.
|
||||||
// and activator/methodfunc/func_result_dispatcher.go
|
// and activator/methodfunc/func_result_dispatcher.go
|
||||||
|
|
||||||
type testControllerMethodResult struct {
|
type testControllerMethodResult struct {
|
||||||
C
|
Ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerMethodResult) Get() Result {
|
func (c *testControllerMethodResult) Get() Result {
|
||||||
|
@ -105,7 +106,7 @@ func TestControllerMethodResult(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type testControllerMethodResultTypes struct {
|
type testControllerMethodResultTypes struct {
|
||||||
C
|
Ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testControllerMethodResultTypes) GetText() string {
|
func (c *testControllerMethodResultTypes) GetText() string {
|
||||||
|
@ -227,16 +228,13 @@ func TestControllerMethodResultTypes(t *testing.T) {
|
||||||
|
|
||||||
type testControllerViewResultRespectCtxViewData struct {
|
type testControllerViewResultRespectCtxViewData struct {
|
||||||
T *testing.T
|
T *testing.T
|
||||||
C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testControllerViewResultRespectCtxViewData) BeginRequest(ctx context.Context) {
|
func (t *testControllerViewResultRespectCtxViewData) BeginRequest(ctx context.Context) {
|
||||||
t.C.BeginRequest(ctx)
|
|
||||||
ctx.ViewData("name_begin", "iris_begin")
|
ctx.ViewData("name_begin", "iris_begin")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testControllerViewResultRespectCtxViewData) EndRequest(ctx context.Context) {
|
func (t *testControllerViewResultRespectCtxViewData) EndRequest(ctx context.Context) {
|
||||||
t.C.EndRequest(ctx)
|
|
||||||
// check if data is not overridden by return View {Data: context.Map...}
|
// check if data is not overridden by return View {Data: context.Map...}
|
||||||
|
|
||||||
dataWritten := ctx.GetViewData()
|
dataWritten := ctx.GetViewData()
|
|
@ -1,8 +1,8 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kataras/iris/mvc2/di"
|
"github.com/kataras/iris/mvc/di"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ func MustMakeHandler(handler interface{}, bindValues ...reflect.Value) context.H
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeHandler accepts a "handler" function which can accept any input that matches
|
// MakeHandler accepts a "handler" function which can accept any input arguments that match
|
||||||
// with the "binders" and any output, that matches the mvc types, like string, int (string,int),
|
// with the "bindValues" types and any output result, that matches the mvc types, like string, int (string,int),
|
||||||
// custom structs, Result(View | Response) and anything that you already know that mvc implementation supports,
|
// custom structs, Result(View | Response) and anything that you already know that mvc implementation supports,
|
||||||
// and returns a low-level `context/iris.Handler` which can be used anywhere in the Iris Application,
|
// and returns a low-level `context/iris.Handler` which can be used anywhere in the Iris Application,
|
||||||
// as middleware or as simple route handler or party handler or subdomain handler-router.
|
// as middleware or as simple route handler or party handler or subdomain handler-router.
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2_test
|
package mvc_test
|
||||||
|
|
||||||
// black-box
|
// black-box
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ import (
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/httptest"
|
"github.com/kataras/iris/httptest"
|
||||||
. "github.com/kataras/iris/mvc2"
|
|
||||||
|
. "github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dynamic func
|
// dynamic func
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
"github.com/kataras/iris/sessions"
|
"github.com/kataras/iris/sessions"
|
||||||
|
|
||||||
mvc "github.com/kataras/iris/mvc2"
|
"github.com/kataras/iris/mvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import "github.com/kataras/iris/core/router"
|
import "github.com/kataras/iris/core/router"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -16,20 +16,36 @@ func getPathParamsForInput(params []macro.TemplateParam, funcIn ...reflect.Type)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
funcInIdx := 0
|
consumedParams := make(map[int]bool, 0)
|
||||||
// it's a valid param type.
|
for _, in := range funcIn {
|
||||||
for _, p := range params {
|
for j, p := range params {
|
||||||
in := funcIn[funcInIdx]
|
if _, consumed := consumedParams[j]; consumed {
|
||||||
paramType := p.Type
|
continue
|
||||||
paramName := p.Name
|
}
|
||||||
// fmt.Printf("%s input arg type vs %s param type\n", in.Kind().String(), p.Type.Kind().String())
|
paramType := p.Type
|
||||||
if paramType.Assignable(in.Kind()) {
|
paramName := p.Name
|
||||||
// fmt.Printf("path_param_binder.go: bind path param func for paramName = '%s' and paramType = '%s'\n", paramName, paramType.String())
|
// fmt.Printf("%s input arg type vs %s param type\n", in.Kind().String(), p.Type.Kind().String())
|
||||||
values = append(values, makeFuncParamGetter(paramType, paramName))
|
if paramType.Assignable(in.Kind()) {
|
||||||
|
consumedParams[j] = true
|
||||||
|
// fmt.Printf("path_param_binder.go: bind path param func for paramName = '%s' and paramType = '%s'\n", paramName, paramType.String())
|
||||||
|
values = append(values, makeFuncParamGetter(paramType, paramName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
funcInIdx++
|
|
||||||
}
|
}
|
||||||
|
// funcInIdx := 0
|
||||||
|
// // it's a valid param type.
|
||||||
|
// for _, p := range params {
|
||||||
|
// in := funcIn[funcInIdx]
|
||||||
|
// paramType := p.Type
|
||||||
|
// paramName := p.Name
|
||||||
|
// // fmt.Printf("%s input arg type vs %s param type\n", in.Kind().String(), p.Type.Kind().String())
|
||||||
|
// if paramType.Assignable(in.Kind()) {
|
||||||
|
// // fmt.Printf("path_param_binder.go: bind path param func for paramName = '%s' and paramType = '%s'\n", paramName, paramType.String())
|
||||||
|
// values = append(values, makeFuncParamGetter(paramType, paramName))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// funcInIdx++
|
||||||
|
// }
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
54
mvc/reflect.go
Normal file
54
mvc/reflect.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package mvc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
|
"github.com/kataras/iris/mvc/di"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
||||||
|
|
||||||
|
func isBaseController(ctrlTyp reflect.Type) bool {
|
||||||
|
return ctrlTyp.Implements(baseControllerTyp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextTyp = reflect.TypeOf((*context.Context)(nil)).Elem()
|
||||||
|
|
||||||
|
func isContext(inTyp reflect.Type) bool {
|
||||||
|
return inTyp.Implements(contextTyp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInputArgsFromFunc(funcTyp reflect.Type) []reflect.Type {
|
||||||
|
n := funcTyp.NumIn()
|
||||||
|
funcIn := make([]reflect.Type, n, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
funcIn[i] = funcTyp.In(i)
|
||||||
|
}
|
||||||
|
return funcIn
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
typeChecker = func(fn reflect.Type) bool {
|
||||||
|
// valid if that single input arg is a typeof context.Context.
|
||||||
|
return fn.NumIn() == 1 && isContext(fn.In(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
hijacker = func(fieldOrFuncInput reflect.Type) (*di.BindObject, bool) {
|
||||||
|
if !isContext(fieldOrFuncInput) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is being used on both func injector and struct injector.
|
||||||
|
// if the func's input argument or the struct's field is a type of Context
|
||||||
|
// then we can do a fast binding using the ctxValue
|
||||||
|
// which is used as slice of reflect.Value, because of the final method's `Call`.
|
||||||
|
return &di.BindObject{
|
||||||
|
Type: contextTyp,
|
||||||
|
BindType: di.Dynamic,
|
||||||
|
ReturnValue: func(ctxValue []reflect.Value) reflect.Value {
|
||||||
|
return ctxValue[0]
|
||||||
|
},
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
|
@ -1,4 +1,4 @@
|
||||||
package mvc2
|
package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
|
@ -11,8 +11,6 @@ var defaultSessionManager = sessions.New(sessions.Config{})
|
||||||
// which requires a binded session manager in order to give
|
// which requires a binded session manager in order to give
|
||||||
// direct access to the current client's session via its `Session` field.
|
// direct access to the current client's session via its `Session` field.
|
||||||
type SessionController struct {
|
type SessionController struct {
|
||||||
C
|
|
||||||
|
|
||||||
Manager *sessions.Sessions
|
Manager *sessions.Sessions
|
||||||
Session *sessions.Session
|
Session *sessions.Session
|
||||||
}
|
}
|
||||||
|
@ -30,10 +28,8 @@ func (s *SessionController) BeforeActivate(ca *ControllerActivator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeginRequest calls the Controller's BeginRequest
|
// BeginRequest initializes the current user's Session.
|
||||||
// and tries to initialize the current user's Session.
|
|
||||||
func (s *SessionController) BeginRequest(ctx context.Context) {
|
func (s *SessionController) BeginRequest(ctx context.Context) {
|
||||||
s.C.BeginRequest(ctx)
|
|
||||||
if s.Manager == nil {
|
if s.Manager == nil {
|
||||||
ctx.Application().Logger().Errorf(`MVC SessionController: sessions manager is nil, report this as a bug
|
ctx.Application().Logger().Errorf(`MVC SessionController: sessions manager is nil, report this as a bug
|
||||||
because the SessionController should predict this on its activation state and use a default one automatically`)
|
because the SessionController should predict this on its activation state and use a default one automatically`)
|
||||||
|
@ -42,3 +38,6 @@ because the SessionController should predict this on its activation state and us
|
||||||
|
|
||||||
s.Session = s.Manager.Start(ctx)
|
s.Session = s.Manager.Start(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EndRequest is here to complete the `BaseController`.
|
||||||
|
func (s *SessionController) EndRequest(ctx context.Context) {}
|
34
mvc2/bind.go
34
mvc2/bind.go
|
@ -1,34 +0,0 @@
|
||||||
package mvc2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kataras/iris/mvc2/di"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
typeChecker = func(fn reflect.Type) bool {
|
|
||||||
// invalid if that single input arg is not a typeof context.Context.
|
|
||||||
return isContext(fn.In(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
hijacker = func(fieldOrFuncInput reflect.Type) (*di.BindObject, bool) {
|
|
||||||
if isContext(fieldOrFuncInput) {
|
|
||||||
return newContextBindObject(), true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// newContextBindObject is being used on both targetFunc and targetStruct.
|
|
||||||
// if the func's input argument or the struct's field is a type of Context
|
|
||||||
// then we can do a fast binding using the ctxValue
|
|
||||||
// which is used as slice of reflect.Value, because of the final method's `Call`.
|
|
||||||
func newContextBindObject() *di.BindObject {
|
|
||||||
return &di.BindObject{
|
|
||||||
Type: contextTyp,
|
|
||||||
BindType: di.Dynamic,
|
|
||||||
ReturnValue: func(ctxValue []reflect.Value) reflect.Value {
|
|
||||||
return ctxValue[0]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
package mvc2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kataras/iris/mvc2/di"
|
|
||||||
"github.com/kataras/golog"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/context"
|
|
||||||
"github.com/kataras/iris/core/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Engine struct {
|
|
||||||
Dependencies *di.D
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEngine() *Engine {
|
|
||||||
return &Engine{
|
|
||||||
Dependencies: di.New().Hijack(hijacker).GoodFunc(typeChecker),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Clone() *Engine {
|
|
||||||
child := NewEngine()
|
|
||||||
child.Dependencies = e.Dependencies.Clone()
|
|
||||||
return child
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Handler(handler interface{}) context.Handler {
|
|
||||||
h, err := MakeHandler(handler, e.Dependencies.Values...)
|
|
||||||
if err != nil {
|
|
||||||
golog.Errorf("mvc handler: %v", err)
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Controller(router router.Party, controller interface{}, beforeActivate ...func(*ControllerActivator)) {
|
|
||||||
ca := newControllerActivator(router, controller, e.Dependencies)
|
|
||||||
|
|
||||||
// give a priority to the "beforeActivate"
|
|
||||||
// callbacks, if any.
|
|
||||||
for _, cb := range beforeActivate {
|
|
||||||
cb(ca)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if controller has an "BeforeActivate" function
|
|
||||||
// which accepts the controller activator and call it.
|
|
||||||
if activateListener, ok := controller.(interface {
|
|
||||||
BeforeActivate(*ControllerActivator)
|
|
||||||
}); ok {
|
|
||||||
activateListener.BeforeActivate(ca)
|
|
||||||
}
|
|
||||||
|
|
||||||
ca.activate()
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package mvc2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
|
||||||
|
|
||||||
func isBaseController(ctrlTyp reflect.Type) bool {
|
|
||||||
return ctrlTyp.Implements(baseControllerTyp)
|
|
||||||
}
|
|
||||||
|
|
||||||
var contextTyp = reflect.TypeOf((*context.Context)(nil)).Elem()
|
|
||||||
|
|
||||||
func isContext(inTyp reflect.Type) bool {
|
|
||||||
return inTyp.Implements(contextTyp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInputArgsFromFunc(funcTyp reflect.Type) []reflect.Type {
|
|
||||||
n := funcTyp.NumIn()
|
|
||||||
funcIn := make([]reflect.Type, n, n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
funcIn[i] = funcTyp.In(i)
|
|
||||||
}
|
|
||||||
return funcIn
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user