doulierong0334 2018-09-24 15:15 采纳率: 100%
浏览 28

恐慌,因为参数必须在Web.Router中为struct而不是接口。

In testing the following code:

package logHandler

import (
    "ezsoft/apiserver_sdk/context"

    "github.com/hsoshiant/web"
)

// Build simply builds a log handler router
//
// Parameters:
//
// - `mainRouter` : the main Router
//
// Returns:
//
// - a sub Router made specifically for logging
func Build(mainRouter *web.Router) *web.Router {
    return mainRouter.Subrouter(context.Context{}, "/log").
        Post("/", doLog)

}

I hit a panic. context.Context is defined thus:

//BaseContext contains all the base context to be helpful when using the utilities
type BaseContext struct {
    Session        session.Store
    ResponseWriter *web.ResponseWriter
    RequestReader  *web.Request
}

//Context contains all values needed when using the utilities
type Context struct {
    BaseContext
    JSONBody      map[string]interface{}
    tokenHandler  *apiToken.APITokenHandlerSt
    OAuthInstance *oAuth2.OAuth2St
}

and with testability/flexibility in mind, the developers wrote the middleware functions to take context.ContextIntf, which context.Context implements, which is defined as follows:

//ContextIntf is the interface to use when using the context interface functions.
type ContextIntf interface {
    SetUniversalHeaders(header map[string]string) map[string]string
    GetInfo() *Context
    GetOAuth() *oAuth2.OAuth2St
}

Here's one such middleware func:

//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(mw AuthenticationMiddlewareIntf, context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
    //Check if the url should be public.
    for _, url := range mw.GetInfo().nonAuthURLs {
        if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
            key := utilities.GetRemoteAdd(r) + ";" + r.URL.Path
            if timeSince, ok := NonAuthSecurityMap[key]; ok {
                var (
                    timeSinceTime, _  = time.Parse(time.UnixDate, timeSince)
                    timeSinceDuration = time.Since(timeSinceTime)
                )
                if timeSinceDuration < nonAuthTimeReset {
                    // will sleep for `nonAuthTimeReset` - `timeSinceDuration` > 0
                    time.Sleep(-(timeSinceDuration - nonAuthTimeReset))
                }
            }
            NonAuthSecurityMap[key] = time.Now().Format(time.UnixDate)
            next(w, r)
            return
        }
    }

    if errSt := CheckForAuthorization(mw, context, r, w); errSt != nil {
        responses.Write(w, responses.Unauthorized(*errSt))
        return
    }
    defer context.GetInfo().Session.SessionRelease(w)
    next(w, r)
}

I am unsure which middleware business functions that package web is checking, let alone what business packages they reside in, and the call stack trace returns no such clues.

The error I get is thus:


                            * You are adding a handler to a router with context type 'Context'
                            *
                            *
                            * Your handler function can have one of these signatures:
                            *
                            * // If you don't need context:
                            * func YourFunctionName(rw web.ResponseWriter, req *web.Request)
                            *
                            * // If you want your handler to accept a context:
                            * func (c *Context) YourFunctionName(rw web.ResponseWriter, req *web.Request)  // or,
                            * func YourFunctionName(c *Context, rw web.ResponseWriter, req *web.Request)
                            *
                            * Unfortunately, your function has this signature: func(context.ContextIntf, web.ResponseWriter, *web.Request)
                            *
                            ************************************************************************************************************************

Why is this requesting a Context struct, instead of the ContextIntf that it implements?!

The stack trace

Looks like this:

goroutine 20 [running]:
testing.tRunner.func1(0xc04213e1e0)
    C:/Go/src/testing/testing.go:742 +0x2a4
panic(0x7633c0, 0xc0421320a0)
    C:/Go/src/runtime/panic.go:502 +0x237
github.com/hsoshiant/web.validateHandler(0x778420, 0x80d8f0, 0x13, 0x8405c0, 0x7b7960)
    D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:286 +0x242
github.com/hsoshiant/web.(*Router).addRoute(0xc042106680, 0x7eeb93, 0x4, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042051f80)
    D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:223 +0x94
github.com/hsoshiant/web.(*Router).Post(0xc042106680, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042106680)
    D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:193 +0x6f
ezsoft/apiserver_sdk/logger/logHandler.Build(0xc0421064e0, 0xc042051f40)
    D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler.go:20 +0xcf
ezsoft/apiserver_sdk/logger/logHandler.TestBuild.func1(0xc04213e1e0)
    D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler_test.go:16 +0x91
testing.tRunner(0xc04213e1e0, 0x80d8e0)
    C:/Go/src/testing/testing.go:777 +0xd7
created by testing.(*T).Run
    C:/Go/src/testing/testing.go:824 +0x2e7

UPDATE : It's hitting the private method doLog, which is defined thus:

func doLog(contextIntf context.ContextIntf, rw web.ResponseWriter, req *web.Request) {
    var (
        logType int    = 0
        code    string = ""
        message string = ""
        context        = contextIntf.GetInfo()
    )
    if val, OK := context.JSONBody["type"]; OK {
        if val1, noErr := val.(float64); noErr {
            logType = int(val1)
        }
    }
    if logType == 0 {
        responses.Write(rw, responses.FreeUnprocessableEntity("Type"))
        return
    }

    if val, OK := context.JSONBody["code"]; OK {
        if val1, noErr := val.(string); noErr {
            code = val1
        } else {
            responses.Write(rw, responses.FreeUnprocessableEntity("Code"))
            return
        }
    }

    if val, OK := context.JSONBody["message"]; OK {
        if val1, noErr := val.(string); noErr {
            message = val1
        }
    }
    if message == "" {
        responses.Write(rw, responses.FreeUnprocessableEntity("message"))
        return
    }
    if code > "" {
        code = " (" + code + ") "
    }
    switch logType {
    case 1:
        logger.Instance.LogError(code + message)
    case 2:
        logger.Instance.LogWarning(code + message)
    case 3:
        logger.Instance.LogInfo(code + message)
    default:
        logger.Instance.LogWarning(code + message)
    }

    responses.Write(rw, responses.OK(0))
}

I still don't get why that argument needs to be a context.Context, or what I, the unit-tester, can do about it.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 RPA正常跑,cmd输入cookies跑不出来
    • ¥15 求帮我调试一下freefem代码
    • ¥15 matlab代码解决,怎么运行
    • ¥15 R语言Rstudio突然无法启动
    • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
    • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
    • ¥15 用windows做服务的同志有吗
    • ¥60 求一个简单的网页(标签-安全|关键词-上传)
    • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
    • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。