Паника, потому что параметры должны быть структурными, а не интерфейсными, в web.Router? - PullRequest
0 голосов
/ 24 сентября 2018

При тестировании следующего кода:

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)

}

Я запаниковал.context.Context определяется следующим образом:

//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
}

и, учитывая тестируемость / гибкость, разработчики написали функции промежуточного программного обеспечения для context.ContextIntf, который реализует context.Context, который определяется следующим образом:

//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
}

Вот одна из таких функций промежуточного программного обеспечения:

//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)
}

Я не уверен, какие бизнес-функции промежуточного программного обеспечения проверяет package web, не говоря уже о том, в каких бизнес-пакетах они находятся.и трассировка стека вызовов не возвращает таких подсказок.

Я получаю следующую ошибку:


                            * 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)
                            *
                            ************************************************************************************************************************

Почему это запрашивает структуру Context вместо ContextIntf, который она реализует?!

Трассировка стека

Выглядит так:

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

ОБНОВЛЕНИЕ : выполняется приватный метод doLog, который определяется следующим образом:

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))
}

Я до сих пор не понимаю, почему этот аргумент должен быть context.Context, или что я, юнит-тестер, могу с этим поделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...