Skip to content

Commit

Permalink
Update to Version 8.4.2 | Read HISTORY.md
Browse files Browse the repository at this point in the history
  • Loading branch information
kataras committed Sep 15, 2017
1 parent 0d8b78a commit 1ed5f99
Show file tree
Hide file tree
Showing 14 changed files with 382 additions and 192 deletions.
42 changes: 42 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,48 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.

# Fr, 15 September 2017 | v8.4.2

## MVC

Support more than one dynamic method function receivers.

```go
package main

import "github.com/kataras/iris"

func main() {
app := iris.New()
app.Controller("/user", new(UserController))
app.Run(iris.Addr("localhost:8080"))
}

type UserController struct { iris.Controller }

// Maps to GET /user
// Request example: http://localhost:8080/user
// as usual.
func (c *UserController) Get() {
c.Text = "hello from /user"
}

// Maps to GET /user/{paramfirst:long}
// Request example: http://localhost:8080/user/42
// as usual.
func (c *UserController) GetBy(userID int64) {
c.Ctx.Writef("hello user with id: %d", userID)
}

// NEW:
// Maps to GET /user/{paramfirst:long}/business/{paramsecond:long}
// Request example: http://localhost:8080/user/42/business/93
func (c *UserController) GetByBusinessBy(userID int64, businessID int64) {
c.Ctx.Writef("fetch a business id: %d that user with id: %d owns, may make your db query faster",
businessID, userID)
}
```

# Th, 07 September 2017 | v8.4.1

## Routing
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Iris may have reached version 8, but we're not stopping there. We have many feat
### 📑 Table of contents

* [Installation](#-installation)
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#th-07-september-2017--v841)
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#fr-15-september-2017--v842)
* [Learn](#-learn)
* [HTTP Listening](_examples/#http-listening)
* [Configuration](_examples/#configuration)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.4.1:https://github.com/kataras/iris/blob/master/HISTORY.md#th-07-september-2017--v841
8.4.2:https://github.com/kataras/iris/blob/master/HISTORY.md#fr-15-september-2017--v842
10 changes: 7 additions & 3 deletions _examples/routing/overview/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ func main() {
// GET: http://any_thing_here.localhost:8080
dynamicSubdomainRoutes.Get("/", info)

app.Delete("/something", func(ctx iris.Context) {
name := ctx.URLParam("name")
ctx.Writef(name)
})

// GET: http://localhost:8080/
// GET: http://localhost:8080/profile/anyusername
// GET: http://localhost:8080/profile/anyusername/backups/any/number/of/paths/here
Expand All @@ -108,13 +113,12 @@ func main() {
// POST: http://localhost:8080/users
// PUT: http://localhost:8080/users
// DELETE: http://localhost:8080/users/42
// DELETE: http://localhost:8080/something?name=iris

// GET: http://admin.localhost:8080
// GET: http://admin.localhost:8080/settings
// GET: http://any_thing_here.localhost:8080
if err := app.Run(iris.Addr(":8080")); err != nil {
panic(err)
}
app.Run(iris.Addr(":8080"))
}

func info(ctx iris.Context) {
Expand Down
Binary file not shown.
5 changes: 4 additions & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub:
Current Version
8.4.0
8.4.2
Installation
Expand Down Expand Up @@ -820,6 +820,8 @@ and it adds its logic to its `BeginRequest`. Source file: https://github.com/kat
Read access to the current route via the `Route` field.
Support for more than one input arguments (map to dynamic request path parameters).
Register one or more relative paths and able to get path parameters, i.e
If `app.Controller("/user", new(user.Controller))`
Expand All @@ -843,6 +845,7 @@ Register one or more relative paths and able to get path parameters, i.e
If `app.Controller("/equality", new(profile.Equality))`
- `func(*Controller) GetBy(is bool)` - `GET:/equality/{param:boolean}`
- `func(*Controller) GetByOtherBy(is bool, otherID int64)` - `GET:/equality/{paramfirst:boolean}/other/{paramsecond:long}`
Supported types for method functions receivers: int, int64, bool and string.
Expand Down
2 changes: 1 addition & 1 deletion iris.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (

const (
// Version is the current version number of the Iris Web Framework.
Version = "8.4.1"
Version = "8.4.2"
)

// HTTP status codes as registered with IANA.
Expand Down
2 changes: 1 addition & 1 deletion mvc/activator/activator.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (t TController) HandlerOf(methodFunc methodfunc.MethodFunc) context.Handler
// the most important, execute the specific function
// from the controller that is responsible to handle
// this request, by method and path.
handleRequest(ctx, c.Method(methodFunc.Index).Interface())
handleRequest(ctx, c.Method(methodFunc.Index))
// if had models, set them after the end-developer's handler.
if hasModels {
t.modelController.Handle(ctx, c)
Expand Down
102 changes: 48 additions & 54 deletions mvc/activator/methodfunc/func_caller.go
Original file line number Diff line number Diff line change
@@ -1,68 +1,62 @@
package methodfunc

import (
"reflect"

"github.com/kataras/iris/context"
)

// FuncCaller is responsible to call the controller's function
// which is responsible
// for that request for this http method.
type FuncCaller interface {
// MethodCall fires the actual handler.
// The "ctx" is the current context, helps us to get any path parameter's values.
//
// The "f" is the controller's function which is responsible
// for that request for this http method.
// That function can accept one parameter.
//
// The default callers (and the only one for now)
// are pre-calculated by the framework.
MethodCall(ctx context.Context, f interface{})
}

type callerFunc func(ctx context.Context, f interface{})
// buildMethodCall builds the method caller.
// We have repeated code here but it's the only way
// to support more than one input arguments without performance cost compared to previous implementation.
// so it's hard-coded written to check the length of input args and their types.
func buildMethodCall(a *ast) func(ctx context.Context, f reflect.Value) {
// if accepts one or more parameters.
if a.dynamic {
// if one function input argument then call the function
// by "casting" (faster).
if l := len(a.paramKeys); l == 1 {
paramType := a.paramTypes[0]
paramKey := a.paramKeys[0]

if paramType == paramTypeInt {
return func(ctx context.Context, f reflect.Value) {
v, _ := ctx.Params().GetInt(paramKey)
f.Interface().(func(int))(v)
}
}

if paramType == paramTypeLong {
return func(ctx context.Context, f reflect.Value) {
v, _ := ctx.Params().GetInt64(paramKey)
f.Interface().(func(int64))(v)
}

}

if paramType == paramTypeBoolean {
return func(ctx context.Context, f reflect.Value) {
v, _ := ctx.Params().GetBool(paramKey)
f.Interface().(func(bool))(v)
}
}

// string, path...
return func(ctx context.Context, f reflect.Value) {
f.Interface().(func(string))(ctx.Params().Get(paramKey))
}

func (c callerFunc) MethodCall(ctx context.Context, f interface{}) {
c(ctx, f)
}

func resolveCaller(p pathInfo) callerFunc {
// if it's standard `Get`, `Post` without parameters.
if p.ParamType == "" {
return func(ctx context.Context, f interface{}) {
f.(func())()
}
}

// remember,
// the router already checks for the correct type,
// we did pre-calculate everything
// and now we will pre-calculate the method caller itself as well.

if p.ParamType == paramTypeInt {
return func(ctx context.Context, f interface{}) {
paramValue, _ := ctx.Params().GetInt(paramName)
f.(func(int))(paramValue)
}
}

if p.ParamType == paramTypeLong {
return func(ctx context.Context, f interface{}) {
paramValue, _ := ctx.Params().GetInt64(paramName)
f.(func(int64))(paramValue)
}
}

if p.ParamType == paramTypeBoolean {
return func(ctx context.Context, f interface{}) {
paramValue, _ := ctx.Params().GetBool(paramName)
f.(func(bool))(paramValue)
// if func input arguments are more than one then
// use the Call method (slower).
return func(ctx context.Context, f reflect.Value) {
f.Call(a.paramValues(ctx))
}
}

// else it's string or path, both of them are simple strings.
return func(ctx context.Context, f interface{}) {
paramValue := ctx.Params().Get(paramName)
f.(func(string))(paramValue)
// if it's static without any receivers then just call it.
return func(ctx context.Context, f reflect.Value) {
f.Interface().(func())()
}
}
89 changes: 89 additions & 0 deletions mvc/activator/methodfunc/func_lexer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package methodfunc

import (
"unicode"
)

const (
tokenBy = "By"
tokenWildcard = "Wildcard" // should be followed by "By",
)

// word lexer, not characters.
type lexer struct {
words []string
cur int
}

func newLexer(s string) *lexer {
l := new(lexer)
l.reset(s)
return l
}

func (l *lexer) reset(trailing string) {
l.cur = -1
var words []string
if trailing != "" {
end := len(trailing)
start := -1

for i, n := 0, end; i < n; i++ {
c := rune(trailing[i])
if unicode.IsUpper(c) {
// it doesn't count the last uppercase
if start != -1 {
end = i
words = append(words, trailing[start:end])
}
start = i
continue
}
end = i + 1
}

if end > 0 && len(trailing) >= end {
words = append(words, trailing[start:end])
}
}

l.words = words
}

func (l *lexer) next() (w string) {
cur := l.cur + 1

if w = l.peek(cur); w != "" {
l.cur++
}

return
}

func (l *lexer) skip() {
if cur := l.cur + 1; cur < len(l.words) {
l.cur = cur
} else {
l.cur = len(l.words) - 1
}
}

func (l *lexer) peek(idx int) string {
if idx < len(l.words) {
return l.words[idx]
}
return ""
}

func (l *lexer) peekNext() (w string) {
return l.peek(l.cur + 1)
}

func (l *lexer) peekPrev() (w string) {
if l.cur > 0 {
cur := l.cur - 1
w = l.words[cur]
}

return w
}
Loading

0 comments on commit 1ed5f99

Please sign in to comment.