Iris: [BUG] when dynamic routing parameters have type judgments, cause cors problem

Created on 24 Jul 2020  ·  16Comments  ·  Source: kataras/iris

Thanks for your contribution!

Describe the bug
when dynamic routing parameters have type judgments, cause cors problem

To Reproduce
Steps to reproduce the behavior:

func main() {
    app := iris.New()
    app.Use(cors.AllowAll())
    app.AllowMethods(iris.MethodOptions)
    app.Delete("user/{id}", user.deleteUser) // no cors problem
    app.Delete("user/{id:uint64}", user.deleteUser) // has cors problem
    _ = app.Run(iris.Addr(":8080"))
}

Expected behavior
Fix it

Desktop (please complete the following information):

  • OS: MacOS
pending-submitter-response bug

Most helpful comment

ok, It seems to have been solved. thanks @kataras

All 16 comments

@CyJaySong what version of Iris did you try? Because on the master it's already fixed. Here is an example which works fine, cors middleware should work too, if it doesn't then it's something wrong in your settings:

package main

import (
    "github.com/kataras/iris/v12"
)

func main() {
    app := iris.New()
    app.Use(middleware)
    app.AllowMethods(iris.MethodOptions)

    app.Get("/user/{id}", delUserStr)           // no cors problem
    app.Get("/user/{id:uint64}", deleteUserInt) // has cors problem
    app.Listen(":8080")
}

func middleware(ctx iris.Context) {
    id := ctx.Params().GetEntry("id")
    ctx.Application().Logger().Infof("middleware ID entry: %v and type of: %T", id.ValueRaw, id.ValueRaw)
    ctx.Next()
}

func delUserStr(ctx iris.Context) {
    id := ctx.Params().Get("id")
    ctx.Writef("id: %v", id)
}

func deleteUserInt(ctx iris.Context) {
    id := ctx.Params().GetUint64Default("id", 0)
    ctx.Writef("id: %v | Type: %T\n", id, id)
}

@kataras v12.1.8,your example not use cors middleware

@CyJaySong it doesn't matter, it uses a middleware. If there was a problem with "type judgments" that middleware wouldn't be fired, the cors middleware works exactly the same. However, thanks for your bug report. In fact, that is a duplication of that: https://github.com/kataras/iris/issues/1549.

The problem is already fixed on master v12.2.0 branch as said above, test it by yourself:

$ cd YOUR_PROJECT_PATH
$ go get -u github.com/kataras/iris/v12@master
$ go run .

And tell me that it didn't work, please close the issue if works as expected. Thank you a lot, and don't hesitate to ask more!

It seems to be solved。 If I meet it again, I will ask. Thanks for your contribution!

You are welcome @CyJaySong!

sir, there are new problem.When two methods use the same route with dynamic parameters, CORS problem is caused

package main

import (
    "github.com/kataras/iris/v12"
)

func main() {
    app := iris.New()
    app.Use(middleware)
    app.AllowMethods(iris.MethodOptions)

    app.Get("/user/{id:uint64}", getUser)       
    app.Patch("/user/{id:uint64}", editUser) 
    app.Listen(":8080")
}

func middleware(ctx iris.Context) {
    id := ctx.Params().GetEntry("id")
    ctx.Application().Logger().Infof("middleware ID entry: %v and type of: %T", id.ValueRaw, id.ValueRaw)
    ctx.Next()
}

func getUser(ctx iris.Context) {
    id := ctx.Params().GetUint64Default("id")
    ctx.Writef("id: %v", id)
}

func editUser(ctx iris.Context) {
    id := ctx.Params().GetUint64Default("id", 0)
    ctx.Writef("id: %v | Type: %T\n", id, id)
}

version: v12.2.0-alpha

@CyJaySong Hmm can you give me a full repository example, so I can run and test? I don't believe there is an issue with CORS and more methods with the same path pattern, cors middleware has nothing to do with the router builder itself.

@CyJaySong There is nothing on the client folder. How can I see the code you used on the client-side?

@kataras Sorry,try again

@CyJaySong replace app.Use(cors.AllowAll()) with app.UseRouter(cors.AllowAll()) and remove the app.AllowMethods(iris.MethodOptions) or better:

```go
api := app.Party("/api")
api.UseRouter(cors.AllowAll())

api.Get("/user", ...)
api.Post("/user", ...)
```

ok, It seems to have been solved. thanks @kataras

I have a question about the above discussion,the following example throws an error. @kataras

package main

import (
    "github.com/google/uuid"
    "github.com/iris-contrib/middleware/cors"
    "github.com/kataras/iris/v12"  // v12.2.0-alpha.0.20201126085352-5b6802d00eaf
    "github.com/kataras/iris/v12/httptest"
    "github.com/kataras/iris/v12/mvc"
    "net/http"
    "testing"
)

func TestCorsAllowOrigins(t *testing.T) {
    origin := "https://iris-go.com"

    app := iris.New()
    app.UseRouter(cors.AllowAll())

    app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
        ctx := app.ContextPool.Acquire(w, r)
        ctx.Values().Set("RequestId", uuid.New().String())
        app.ServeHTTPC(ctx)
        app.ContextPool.Release(ctx)
    })

    mvc.New(app.Party("/")).Handle(new(ControllerT1))

    e := httptest.New(t, app)

    e.GET("/param/1").WithHeader("Origin", origin).Expect().Status(httptest.StatusOK)
    e.DELETE("/param/1").WithHeader("Origin", origin).Expect().Status(httptest.StatusOK)

    // test options , expect 200, got 404
    e.OPTIONS("/param/1").WithHeader("Origin", origin).
        WithHeader("Access-Control-Request-Method", "GET").
        WithHeader("Access-Control-Request-Headers", "Content-Type").
        Expect().Status(httptest.StatusOK)

}

type ControllerT1 struct {
    Ctx iris.Context
}

func (*ControllerT1) GetParamBy(id uint) interface{} {
    return id
}

func (*ControllerT1) DeleteParamBy(id uint) interface{} {
    return id
}

Hello @Ostaer, this is expected as you don't call the router in the app.WrapRouter, instead you call the ServeHTTPC which directly fires the routing matching handler without respecting the app.UseRouter(cors...) - the router filters (UseRouter) ran on main router (router(w,r) inside the app.WrapRouter but you skip this part so these will not ran). You do NOT need to use app.WrapRouter for request id. Instead do that:

import "github.com/kataras/iris/v12/middleware/requestid"
    app := iris.New()
    app.UseRouter(cors.AllowAll())
    app.UseRouter(requestid.New([here you can register your own generator, by-default it uses the google's uuid]))
    mvc.New(app.Party("/")).Handle(new(ControllerT1))
    // [...]
Was this page helpful?
0 / 5 - 0 ratings