所以我是新手,目前我尝试使用 chi 构建一个小 REST-API(我喜欢它)。昨天我遇到了一个问题,我不太明白。
在我的小测试项目中,我有一个main.go文件,其中包含路由器实例化、添加中间件和启动服务器的主要功能:
func main() {
router := chi.NewRouter()
// Middleware
router.Use(middleware.RequestID)
router.Use(middleware.RealIP)
router.Use(middleware.Logger)
router.Use(middleware.Recoverer)
// Routes
router.Post("/login", users.Login)
router.Post("/register", users.Register)
router.With(users.LoginRequired).Route("/users", func(r chi.Router) {
r.Get("/{user_id}", users.GetUser)
})
// Start Server
port := ":8080"
log.Printf("Server starting at port %v\n", port)
log.Fatal(http.ListenAndServe(port, router))
}
Run Code Online (Sandbox Code Playgroud)
首先,问题不存在,因为我在main.go文件中定义了所有处理程序函数,并且 GetUser 函数按预期工作并从我的“数据库”(包含 3 个用户的数组)返回一个用户:
func GetUser(w http.ResponseWriter, r *http.Request) {
uID := chi.URLParam(r, "user_id") // Problem when not in main -> uID = ""
id, err := strconv.Atoi(uID)
if err …Run Code Online (Sandbox Code Playgroud) 我正在使用 chi 在 golang 中开发一个宁静的服务。我正在尝试创建如下路线
r.Mount("/api/dest", router.NewDestRouter(chi.NewRouter(), destSrv).InitRoutes())
func (dr *DestRouter) InitRoutes() http.Handler {
dr.router.Post("/{number}/product?version={v}", handlers.HandleProduct(dr.dest))
return dr.router
}
Run Code Online (Sandbox Code Playgroud)
但是我尝试通过邮递员到达此端点,但未找到 404
http://localhost:8345/api/dest/1235abc/product?version=1
Run Code Online (Sandbox Code Playgroud)
我可以知道这里的问题吗?
我在测试 go-chi 路线时遇到问题,特别是带有路径变量的路线。运行服务器go run main.go工作正常,并且使用路径变量请求路由的行为符合预期。
当我运行路由测试时,我总是收到 HTTP 错误:Unprocessable Entity。注销发生的情况后articleID,似乎articleCtx无法访问路径变量。不确定这是否意味着我需要articleCtx在测试中使用,但我已经尝试ArticleCtx(http.HandlerFunc(GetArticleID))并收到错误:
panic: interface conversion: interface {} is nil, not *chi.Context [recovered]
panic: interface conversion: interface {} is nil, not *chi.Context
运行服务器:go run main.go
测试服务器:go test .
我的来源:
// main.go
package main
import (
"context"
"fmt"
"net/http"
"strconv"
"github.com/go-chi/chi"
)
type ctxKey struct {
name string
}
func main() {
r := chi.NewRouter()
r.Route("/articles", func(r chi.Router) {
r.Route("/{articleID}", func(r …Run Code Online (Sandbox Code Playgroud) 使用 Chi 路由器设置中间件时chi.Use和之间有什么区别。chi.With
我想完全分离客户端和服务器,所以我创建了一个带有vue init webpack my-project. 在这个项目中,我将 vue-router 用于我的所有路由(这包括特殊路径,例如/user/SOMEID..
这是我的 routes.js 文件:
import App from './App.vue'
export const routes = [
{
path: '/',
component: App.components.home
},
{
path: '/user/:id',
component: App.components.userid
},
{
path: '*',
component: App.components.notFound
}
]
Run Code Online (Sandbox Code Playgroud)
当我使用npm run dev一切完美运行应用程序时。我现在准备部署到云中,所以我运行了npm run build. 由于我需要使用 HTTP 服务器,因此我决定也使用 Go 来实现……这是我的 Go 文件:
package main
import (
"fmt"
"github.com/go-chi/chi"
"github.com/me/myproject/server/handler"
"net/http"
"strings"
)
func main() {
r := chi.NewRouter()
distDir := "/home/me/code/go/src/github.com/me/myproject/client/dist/static"
FileServer(r, "/static", http.Dir(distDir)) …Run Code Online (Sandbox Code Playgroud) 在 中go-chi,在单个路由级别设置中间件,而不仅仅是针对所有路由全局设置
// Routes creates a REST router
func Routes() chi.Router {
r := chi.NewRouter()
r.Use(middleware.Captcha)
r.Post("/", Login)
return r
}
Run Code Online (Sandbox Code Playgroud)
如何Login指定唯一的中间件或从通用中间件中排除?
我有一个中间件来记录此服务访问。但我在谷歌上搜索了几次后,对进行单元测试感到困惑。我还没有找到解决这个问题的正确方法
package accesslog
import (
"net/http"
"time"
"github.com/go-chi/chi/middleware"
"transactionService/pkg/log"
)
func Handler(logger log.Logger) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = log.WithRequest(ctx, r)
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
start := time.Now()
defer func() {
logger.With(ctx, "duration", time.Since(start), "status", ww.Status()).
Infof("%s %s %s %d %d", r.Method, r.URL.Path, r.Proto, ww.Status(), ww.BytesWritten())
}()
next.ServeHTTP(ww, r.WithContext(ctx))
}
return http.HandlerFunc(fn)
}
}
Run Code Online (Sandbox Code Playgroud) 我对特定的路由集使用特定的中间件
r.Route("/platform", func(r chi.Router) {
r.Use(authService.AuthMiddleware)
r.Get("/{id}/latest", RequestPlatformVersion)
})
Run Code Online (Sandbox Code Playgroud)
现在我如何访问这个中间件id中的 url 参数AuthMiddleware
func (s *Service) AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(chi.URLParam(r, "id"))
id := chi.URLParam(r, "id")
if id > 100 {
http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
return
}
}
return http.HandlerFunc(fn)
}
Run Code Online (Sandbox Code Playgroud)
但是,即使正在运行中间件并且正在调用特定路由,id 参数也会打印为空字符串
我正在开发一个 Web 服务应用程序,其端点/加密/汇率接受两个 \xe2\x80\x9csymbols\xe2\x80\x9d 货币作为输入。Web 服务应在数据库中搜索这些字符之间的货币兑换数据,如果数据库中没有值,或者时间戳值与当前值相差超过 1 分钟,则向服务 API 发出请求:\n https://min-api.cryptocompare.com/documentation \n因此,我创建了结构体和 go-chi 路由器。但我不知道如何构建一个工作处理程序来从 URL 获取参数,例如: https: //min-api.cryptocompare.com/data/price?fsym=BTC&tsyms =USD
\n\npackage main\n\nimport (\n "github.com/go-chi/chi"\n "net/http"\n)\n\ntype Crypto struct {\n Cur1 string\n Cur2 string\n Rate float64\n Timestamp int64\n}\nfunc main() {\n port := ":3000"\n r := chi.NewRouter()\n r.Get("/", func(w http.ResponseWriter, r *http.Request) {\n w.Write([]byte("Connected"))\n })\n\n http.ListenAndServe(port, r)\nRun Code Online (Sandbox Code Playgroud)\n\n我想我可以尝试为处理程序主体上的第一个值创建 Cur1:
\n\ncur1 = r.FormValue("cur1")\nRun Code Online (Sandbox Code Playgroud)\n\n同样对于第二个值:
\n\nCur2 = r.FormValue("cur2") \nRun Code Online (Sandbox Code Playgroud)\n\n最终请求将是:~/get_rates?cur1=eth&cur2=btc
\n在下面的程序中我有两个路由器。其中一个在公共接入点上工作localhost:3000并充当公共接入点。它还可以将带有数据的请求发送到localhost:8000正在处理数据的另一个本地地址。第二个路由器正在工作localhost:8000并处理第一个路由器的处理请求。
第一路由器向第二使用功能发送带有上下文的请求http.NewRequestWithContext()。该值将被添加到上下文中,并且上下文将被添加到请求中。当请求到达第二个路由器时,它没有之前添加的值。
有些东西(例如错误处理)没有被编写,以便不在这里发布代码墙。
package main
import (
"bytes"
"context"
"net/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
)
func main() {
go func() {
err := http.ListenAndServe(
"localhost:3000",
GetDataAndSolve(),
)
if err != nil {
panic(err)
}
}()
go func() {
err := http.ListenAndServe( // in GetDataAndSolve() we send requests
"localhost:8000", // with data for processing
InternalService(),
)
if err != nil {
panic(err)
}
}()
// interrupt := make(chan os.Signal, 1)
// signal.Notify(interrupt, syscall.SIGTERM, syscall.SIGINT) …Run Code Online (Sandbox Code Playgroud) go ×10
go-chi ×10
middleware ×4
rest ×3
api ×1
http ×1
parameters ×1
unit-testing ×1
url ×1
vue-router ×1
vue.js ×1
vuejs2 ×1