fasthttp / router Goto Github PK
View Code? Open in Web Editor NEWRouter implementation for fasthttp
License: BSD 3-Clause "New" or "Revised" License
Router implementation for fasthttp
License: BSD 3-Clause "New" or "Revised" License
Hello, this repo use github.com/savsgio/gotils which is gpl3. Can you look at replacing with a compatible license for fasthttp/router? Thanks.
Like Gin Cors()
Or:
ctx.Response.Header.Set("Access-Control-Allow-Origin", "*")
Line 260 in cc03ff3
The documentation for the function router.Lookup mentions a third parameter and doesn't match the actual function body:
// Lookup allows the manual lookup of a method + path combo.
// This is e.g. useful to build a framework around this router.
// If the path was found, it returns the handler function and the path parameter
// values. Otherwise the third return value indicates whether a redirection to
// the same path with an extra / without the trailing slash should be performed.
I guess it should be:
// Lookup allows the manual lookup of a method + path combo.
// This is e.g. useful to build a framework around this router.
// If the path was found, it returns the handler function. Otherwise the second return value indicates whether a redirection to
// the same path with an extra / without the trailing slash should be performed.
It also doesn't metion what the ctx value is used for when looking up a handler and i can't really figure out why the ctx is needed here
i had this code in 'net/http' and we were serving static directory using this code
but now we have shifted our code(projects) from net/http to fasthttp
and in fasthttp there is no way to serve files from embed
//go:embed static/*
var static embed.FS
fsRoot, _ := fs.Sub(static, "static")
fsStatic := http.FileServer(http.FS(fsRoot))
s.router.PathPrefix("/").Handler(fsStatic)
if i have the following routes:
"/regex/{c1:big_alt|alt|small_alt}/{rest:*}"
and
/regex/{path:*}
the following path will match with the first route:
"/regex/small_alt/hello"
1.3.2 changed the behavior of RedirectFixedPath
. Before 1.3.2, double slashes would be ignored when RedirectFixedPath
was set to false. As of 1.3.2, a 404 is now returned.
Modifying the example in the README slightly:
package main
import (
"fmt"
"log"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
func Index(ctx *fasthttp.RequestCtx) {
ctx.WriteString("Welcome!")
}
func Hello(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Hello, %s!\n", ctx.UserValue("name"))
}
func main() {
r := router.New()
r.RedirectFixedPath = false
r.GET("/", Index)
r.GET("/hello/{name}", Hello)
log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}
On 1.3.1:
$ curl -v http://localhost:8080/hello//fdasf
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /hello//fdasf HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: fasthttp
< Date: Thu, 10 Sep 2020 18:17:30 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 14
<
Hello, fdasf!
* Connection #0 to host localhost left intact
On 1.3.2:
$ curl -v http://localhost:8080/hello//fdasf
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /hello//fdasf HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: fasthttp
< Date: Thu, 10 Sep 2020 18:17:53 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 9
<
* Connection #0 to host localhost left intact
Hey^^
I use the following line to achieve a regex validation on a path:
router.GET("/{filepath:^(?!api).*}", frontend.RequestHandler)
I want that this route only applies if the path does not begin with api
. My problem is that the program panics:
panic: path must begin with '/' in path ''
goroutine 1 [running]:
github.com/fasthttp/router/radix.panicf(...)
C:/Users/lukas/go/pkg/mod/github.com/fasthttp/[email protected]/radix/utils.go:13
github.com/fasthttp/router/radix.(*Tree).Add(0xc0000a8070, 0xea52fc, 0x0, 0xc0000a8050)
C:/Users/lukas/go/pkg/mod/github.com/fasthttp/[email protected]/radix/tree.go:24 +0x44a
github.com/fasthttp/router.(*Router).Handle(0xc0000ac000, 0xe9e85a, 0x3, 0xea52fc, 0x18, 0xc0000a8050)
C:/Users/lukas/go/pkg/mod/github.com/fasthttp/[email protected]/router.go:198 +0x1f3
github.com/fasthttp/router.(*Router).GET(...)
C:/Users/lukas/go/pkg/mod/github.com/fasthttp/[email protected]/router.go:74
r.ServeFilesCustom("/assets/{filepath:*}", &fasthttp.FS{
Root: "./assets",
PathNotFound: NotFound, // here I can handle and LOG it if needed
Compress: true,
})
And the system outputs to console the message:
2020/09/04 10:20:42 5.411 #0000000100000002 - 127.0.0.1:8090<->127.0.0.1:58104
- GET http://test.local:8080/assets/js/asfgsf - cannot open file "./assets/js/asfgsf": open ./assets/js/asfgsf: The system cannot find the file specified.
Is there a way to suppress this message? What's it for in the console? This is only a useless waste of resources.
New feature "path validation" breaks my group usage
I have router structure like:
apiMonitors := router.Group("/monitors")
apiMonitors.GET("", h...)
apiMonitors.POST("", h...)
apiMonitors.GET("/{oid}", h...)
apiMonitors.PUT("/{oid}", h...)
apiMonitors.DELETE("/{oid}", h...)
apiMonitors.GET("/{jobId}/run", h...)
apiMonitors.GET("/{jobId}/complete", h...)
apiMonitors.GET("/{jobId}/fail", h...)
apiMonitors.GET("/{jobId}/pause", h...)
and now I get error panic: path must begin with '/' in path ''
Will this be fixed or do I need to rebuild my structure?
This started with 1.0.0.
Error:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x69823b]
goroutine 20 [running]:
github.com/valyala/fasthttp.(*RequestCtx).SetUserValue(...)
/home/greg/go/pkg/mod/github.com/valyala/[email protected]/server.go:581
github.com/fasthttp/router/radix.(*node).getFromChild(0xc0000b45a0, 0xc00001e1d6, 0xa, 0x0, 0x10, 0x9592bc)
/home/greg/go/pkg/mod/github.com/fasthttp/[email protected]/radix/node.go:307 +0x59b
github.com/fasthttp/router/radix.(*node).getFromChild(0xc0000b4420, 0xc00001e1d1, 0xf, 0x0, 0x410404, 0xc000057a10)
/home/greg/go/pkg/mod/github.com/fasthttp/[email protected]/radix/node.go:302 +0x4b1
github.com/fasthttp/router/radix.(*Tree).Get(0xc0000b2040, 0xc00001e1d0, 0x10, 0x0, 0xc00009d678, 0x10)
/home/greg/go/pkg/mod/github.com/fasthttp/[email protected]/radix/tree.go:88 +0x1f7
github.com/fasthttp/router.(*Router).allowed(0xc0000b4360, 0xc00001e1d0, 0x10, 0xc00001e138, 0x4, 0x0, 0x3200000000000000)
/home/greg/go/pkg/mod/github.com/fasthttp/[email protected]/router.go:405 +0x5dc
github.com/fasthttp/router.(*Router).Handler(0xc0000b4360, 0xc000078000)
/home/greg/go/pkg/mod/github.com/fasthttp/[email protected]/router.go:511 +0x37a
github.com/valyala/fasthttp.(*Server).serveConn(0xc0000fc000, 0x7a4f40, 0xc0000b2088, 0x0, 0x0)
/home/greg/go/pkg/mod/github.com/valyala/[email protected]/server.go:2041 +0x554
github.com/valyala/fasthttp.(*workerPool).workerFunc(0xc0000beb40, 0xc0000a6460)
/home/greg/go/pkg/mod/github.com/valyala/[email protected]/workerpool.go:223 +0xc0
github.com/valyala/fasthttp.(*workerPool).getCh.func1(0xc0000beb40, 0xc0000a6460, 0x6bb4a0, 0xc0000a6460)
/home/greg/go/pkg/mod/github.com/valyala/[email protected]/workerpool.go:195 +0x35
created by github.com/valyala/fasthttp.(*workerPool).getCh
/home/greg/go/pkg/mod/github.com/valyala/[email protected]/workerpool.go:194 +0x101
Code:
package main
import (
"log"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
func main() {
r := router.New()
r.GET("/{version}/{service}/{value}", func(ctx *fasthttp.RequestCtx) {})
log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}
Request:
curl -d '{}' 'localhost:8080/does/not/matter'
Hi 👋
What do you think about adding the possibility to pass a wildcard to the method
argument in the Handle
function ?
It would be great to permit to just pass all requests, independently from the method, to the same handler.
I have a service which for a specific Route:
The wildcard on the URL is super handy here because it permits to just write the base URL to the route (ex: /products/{any:*}
) and call my handler doing the authentication and then pass-through. Therefore if I add new endpoints in my destination service, I won't need to update this one.
But since there is no equivalent for the methods, if I add endpoints with new methods in my destination service, I need to think to add equivalents in the authentication one. Making the maintainability harder and more error prone.
Thank you for considering this proposal and for this amazing router!
Will there be this routing mode in the future?
Due to historical reasons, we have a problem as follows:
/xxx/xxxx/aaa
/xxx/xxxx/aaa/
Two routes (can be registered), when RedirectTrailingSlash is false, these two can be matched
In fasthttp, only one of these two can be registered. When registering /xxx/xxxx/aaa/, when routing /xxx/xxxx/aaa, you can redirect. I want to be able to match。
I temporarily modified the code and it works normally, but I don’t know if there are hidden dangers. Can you reply to the next and support me so that I can update in time, or tell if there are any hidden dangers?
Code:
types.go
type Router struct {
...
//When redirecting, it will be combined according to the path of the child to re matchFor example
//For example:/xxx/xxx/aaa => /xxx/xxx/aaa/ or /xxx/xxx/aaa/ => /xxx/xxx/aaa
NoRedirectWithRootPath bool
...
}
router.go line:341
func (r *Router) tryRedirect(ctx *fasthttp.RequestCtx, tree *radix.Tree, tsr bool, method, path string) bool {
...
if tsr && r.RedirectTrailingSlash {
uri := bytebufferpool.Get()
getRedirectUri(ctx,path,uri)
ctx.Redirect(uri.String(), code)
bytebufferpool.Put(uri)
return true
}
if tsr && r.NoRedirectWithRootPath {
uri := bytebufferpool.Get()
getRedirectUri(ctx,path,uri)
if uri.Len() > 0 {
if parHandler ,_:= tree.Get(uri.String(), ctx); parHandler != nil {
parHandler(ctx)
}
}
bytebufferpool.Put(uri)
return true
}
...
}
func getRedirectUri(ctx *fasthttp.RequestCtx,path string,uri *bytebufferpool.ByteBuffer) {
if len(path) > 1 && path[len(path)-1] == '/' {
uri.SetString(path[:len(path)-1])
} else {
uri.SetString(path)
uri.WriteString("/")
}
queryBuf := ctx.URI().QueryString()
if len(queryBuf) > 0 {
uri.WriteByte(questionMark)
uri.Write(queryBuf)
}
}
Hi!
Let say I have
GET("/customer/:id", handler)
How can I find the original path "/customer/:id" inside func handler() ?
Thank you
MatchedRoutePathParam
is used to store the original path registered by the user in ctx.UserValues
. From the code, I found that this variable is defined with some random byte strings at runtime. What's the reasoning behind keeping this variable as random? Side effect of this is any downstream user of the library, including arbitrary middleware/wrappers need to now import this variable everywhere.
Additionally, do you think passing this variable from the user makes sense?
Thanks!
I want to export my metric with prometheus. But how I add the handler
Should have a way to list/print all the registered routes and methods.
I have some problems routing some requests when using catch-all params. I am using version v1.1.1 and this is the code:
package main
import (
"log"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
func Catchall(ctx *fasthttp.RequestCtx) {
ctx.WriteString("Catchall!")
}
func Specific(ctx *fasthttp.RequestCtx) {
ctx.WriteString("Specific!")
}
func main() {
r := router.New()
r.ANY("/{path:*}", Catchall)
r.POST("/specific", Specific)
log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}
I would expect any request different than POST /specific
to be caught by the Catchall
handler, but this is not what is actually happening. For the exact POST /specific
and any request that is not starting with /specific
it works fine but for the following cases it is not:
/specific
/specific/whatever
/specific/whatever
The server is just returning a redirect. I think this is due to the radix tree, but I would expect another behavior.
fasttools ➤ go build
go: downloading github.com/fasthttp/router v0.5.1
go: downloading github.com/valyala/fasthttp v1.5.0
verifying github.com/valyala/[email protected]: github.com/valyala/[email protected]: Get https://sum.golang.org/lookup/github.com/valyala/[email protected]: dial tcp 172.217.27.145:443: i/o timeout
verifying github.com/fasthttp/[email protected]: github.com/fasthttp/[email protected]: Get https://sum.golang.org/lookup/github.com/fasthttp/[email protected]: dial tcp 172.217.27.145:443: i/o timeout
Would be nice if there was a way to specify middlewares for Group as otherwise currently you have to add route filtering in middlewares or add checks in all handlers
Hello, I just new to Go-Lang and want to create some microservice to do some query to a database. How to pass sql.DB object to request handler so there is only one sql.DB connection object?
I've search some discussion before like https://stackoverflow.com/questions/36754619/usage-of-global-variables-with-http-handlers-in-golang and https://github.com/buaazp/fasthttprouter/issues/48#issuecomment-474375859
But still clueless about this. Please help
Hello,
I've been using the router for some time now, but I'm having trouble figuring out the path being called to include in the Datadog.
Below is an example of middleware, retrieves the path already with parameter value, but I would like to display it as the original path.
It is showing with the concatenated parameter and not as declared.
https://github.com/qgxpagamentos/ddfasthttp
``
func Middleware(f fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
if _, ok := os.LookupEnv("DATADOG_ENABLED"); !ok {
f(ctx)
return
}
spanOpts := []ddtrace.StartSpanOption{
tracer.ResourceName(string(ctx.Request.Header.Method()) + " " + string(ctx.Request.URI().Path())),
}
var r http.Request
if e := fasthttpadaptor.ConvertRequest(ctx, &r, true); e != nil {
panic(e)
}
span, context := StartRequestSpan(&r, spanOpts...)
ctx.SetUserValue(DataDogTransaction, context)
f(ctx)
statusCode := ctx.Response.StatusCode()
FinishRequestSpan(span, statusCode)
}
router.GET("/hello", helloHandlerFunc)
router.GET("/{param}", paramHandler)
When I try to get /hellowhatever
, or even any that start with "h" like /hey
, it returns ERR_TOO_MANY_REDIRECTS
.
Why is this happening?
I use code from: https://github.com/fasthttp/router/tree/v1.3.1/_examples/basic
All in default.
Checking "fix wrong cases and remove superfluous path elements (like ../ or //)" because my currect web-server doesn't do it.
http://localhost:8080/ works, it is normal
http://localhost:8080///// works too, not expected
http://localhost:8080////hello/////name works, does not redirect to correct http://localhost:8080/hello/name
But if I use capital letters:
http://localhost:8080////hELLO/////name
it correctly redirects to http://localhost:8080/hello/name removing reduntant slashes.
r := New()
v1 := r.Group("/v1")
v1.GET("/foo/{id}/{pageSize}/{page}", func(ctx *fasthttp.RequestCtx) {
id1 = ctx.UserValue("id").(string)
pageSize = ctx.UserValue("pageSize").(string)
page = ctx.UserValue("page").(string)
routed1 = true
})
v1.DELETE("/foo/{id}/{iid}", func(ctx *fasthttp.RequestCtx) {
id2 = ctx.UserValue("id").(string)
iid = ctx.UserValue("iid").(string)
routed2 = true
})
the /foo/{id}/{iid}
path will not been route.
Hey! I forked flf2ko/fasthttp-prometheus and changed it to your router implementation. Can you add link to you readme for the Mnwa/fasthttprouter-prometheus?
Hello. I really like this project. I would like to request to add a method to apply middleware to a whole group/router. I'm willing to contribute if needed
Hello,
Is this possible to define optional parameter like
/foo/:barvalue/?:baroption=1 // < baroption is optional we can say /foo/value and /foo/value/?option=1
What is the best way to achieve that with the router ?
Translate something like that with the framework ?
GET /foo?option=value&bar=otheroption
Hi, I see there is a trees.Add() when adding a route. If I want to delete a route or update the handler of an existing route, is there API for manipulating the "trees"?
hello, I want to ask about how to do unit testing when I have url parameters
(e.g /:name) on my url ?
because at this fasthttp they uses requestCtx
, I am a little confused to do unit tests when I have url parameters.
Thanks before,
My router for domain http://st.domain.test
func StaticRouter(r *router.Router) {
r.NotFound = NotFound
r.MethodNotAllowed = MethodNotAllowed
r.PanicHandler = InternalServerError
r.ServeFilesCustom("/{filepath:*}", &fasthttp.FS{
Root: "./static",
PathNotFound: NotFound,
CacheDuration: time.Hour * 24 * 30,
})
}
For not existing request, for example, http://st.domain.test:8090/abrakadabra, router write to console:
2020/12/17 10:11:07 0.960 #0000000800000003 - 127.0.0.1:8090<->127.0.0.1:50255 - GET http://st.domain.test:8090/abrakadabra - cannot open file "./static/abrakadabra": open ./static/abrakadabra: The system cannot find the file specified.
And calls handler for PanicHandler. I expect "NotFound" in this situation.
#>go get github.com/fasthttp/router
go get github.com/fasthttp/router
go: github.com/fasthttp/router upgrade => v1.1.3
go: downloading github.com/fasthttp/router v1.1.3
go get: github.com/fasthttp/[email protected]: verifying module: checksum mismatch
downloaded: h1:q042AM9cSgVNvpG1T+lMAiL1PXLcTs94n1pCDQ737ss=
sum.golang.org: h1:xxYAxTON68tX8pXwdw3cCPOYvKoXIbfrouBEuG6kFsk=
SECURITY ERROR
This download does NOT match the one reported by the checksum server.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.
Hello, may I ask, how can I implement the filter, before all requests, after the request add the filter, in the outer layer
Hello, I have a route
r.GET("/file/:file.json", routes.GetFile)
and request GET localhost:8080/file/somefile.json
I am expecting ctx.UserValue("file") -> "somefile"
but received ctx.UserValue("file.json") -> somefile.json
How to correctly process this behaviour, without any additional trimming and etc?
Hi!
I'm trying to use autocannon to test the performance.
This is the configuration:
autocannon -c 10 -d 30 -m POST -b {"data":"teste"} http://localhost:3001/index
just changed GET to POST. But I get timeout for all the connections.
This is a bug??
I have a very restrictive requirement
I need to support path likes
/foo
/foo/
without redirect from one form to the other ( in other words, the last trailing slash should be ignored )
https://github.com/buaazp/fasthttprouter works fine for this, but fasthttp/router panics
panic: a handler is already registered for path '/stream/'
goroutine 1 [running]:
github.com/fasthttp/router/radix.(*Tree).Add(0xc0003ee640, {0xc000120540, 0x8}, 0xc0003ed110)
how can I achieve it?
How can i get the matched route in my handle?
Example:
Assuming that i've registered the route
r.GET("/hello/{name}", Hello)
In Hello handle i would like to get "/hello/{name}" path
Is it possible?
package main
import (
"fmt"
"log"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
func Index(ctx *fasthttp.RequestCtx) {
ctx.WriteString("Welcome!")
}
func Hello(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Hello, %s!\n", ctx.UserValue("name"))
}
func main() {
r := router.New()
r.GET("/hello/test", Index)
r.GET("/hello/{name}", Hello)
fmt.Println("starting")
log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}
GET: /hello/test returns "Welcome!"
GET: /hello/test1 hangs indefinitely
GET: /hello/tes returns "Hello, tes!"
Hi, in my server i have routes for mobile app and site.
I split routes by Group
Can I get route.Group with middleware ?
Something Like that:
r := router.New()
mobileRoutes := r.Group("/api/v1/mibile")
//...
mobileRoutes = middleware.CheckJWT(mobileRoutes)
siteRoutes := r.Group("/api/v1/site")
//...
siteRoutes = middleware.Cors(siteRoutes )
It seems this broke in 1.1.x. For example, using the "trivial example" from the README.md:
$ curl -v -d {} http://localhost:8080/hello/fdas
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /hello/fdas HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 2 out of 2 bytes
< HTTP/1.1 404 Not Found
< Server: fasthttp
< Date: Mon, 01 Jun 2020 17:33:52 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 9
<
* Connection #0 to host localhost left intact
Not Found
Whereas with older version:
$ curl -v -d {} http://localhost:8080/hello/fdas
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /hello/fdas HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 2 out of 2 bytes
< HTTP/1.1 405 Method Not Allowed
< Server: fasthttp
< Date: Mon, 01 Jun 2020 17:38:19 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 18
< Allow: GET, OPTIONS
<
* Connection #0 to host localhost left intact
Method Not Allowed
The following code does not handle trailing slashes as expected. The docs say that requests with a trailing slash will be handled the same as without a trailing slash. This does not work in the below code;
package main
import (
"fmt"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
"log"
"time"
)
var (
s = &fasthttp.Server{
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
GetOnly: true,
}
)
func greet(ctx *fasthttp.RequestCtx) {
ctx.WriteString(fmt.Sprintf("Hi %s\n", ctx.UserValue("name").(string)))
}
func main() {
r := router.New()
r.RedirectTrailingSlash = true
r.GET("/:name", greet)
s.Handler = r.Handler
log.Fatal(s.ListenAndServe(":8080"))
}
Testing this gives;
jonathan@ubuntu:~$ curl 127.0.0.1:8080/joe
Hi joe
jonathan@ubuntu:~$ curl 127.0.0.1:8080/joe/
jonathan@ubuntu:~$
If there is a trailing slash the handler is not executed. How would I fix this?
Same as buaazp/fasthttprouter#49.
I want use /
path for render index page and /:slug
for render specific content by it's :slug
. I am aware about the hack through router.NotFound
, but, firstly, this is not most obvious way, and secondly, it requires additional validations for the correct transitions between the necessary pages.
func main() {
...
r := router.New()
handler.RegisterAPI(r.Group("/api")) // api
handler.RegisterTemplates(r) // renders
}
func (h *MyHandlers) RegisterTemplates(g *router.Router) {
g.GET("/", h.RenderIndex)
g.GET("/:slug", h.RenderSlug)
}
func (h *MyHandlers) RegisterAPI(g *router.Router) {
g.GET("/", h.ShowAll)
g.GET("/:slug", h.ShowOne)
}
user := sm.Group("/user ")
user .GET("", h.UserHomePage)
error:
panic: path must begin with '/' in path ''
group.go
`func (g *Group) GET(path string, handler fasthttp.RequestHandler) {
validatePath(path)
g.router.GET(g.prefix+path, handler)
}`
Should it be changed to
`func (g *Group) GET(path string, handler fasthttp.RequestHandler) {
validatePath(g.prefix+path)
g.router.GET(g.prefix+path, handler)
}`
Hello.
I currently try to serve a static web frontend under the /dashboard/*
route:
router.GET("/", func(ctx *fasthttp.RequestCtx) {
ctx.Redirect("/dashboard", fasthttp.StatusMovedPermanently)
})
router.GET("/dashboard/{filepath:*}", fasthttp.FSHandler("./web", 0))
However, it seems like the server includes the /dashboard/
prefix when it looks for local files:
2021/06/27 13:23:50 2.483 #0000000100000007 - 127.0.0.1:8080<->127.0.0.1:47280 - GET http://localhost:8080/dashboard/ - cannot open file "./web/dashboard": open ./web/dashboard: no such file or directory
Is there a way to prevent this?
Hi there! :)
I've prepared a short snippet program localizing the issue:
go.mod:
module test
go 1.14
require (
github.com/fasthttp/router v1.2.4
github.com/valyala/fasthttp v1.15.1
)
main.go:
package main
import (
httprouter "github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
func main() {
router := httprouter.New()
var s string
router.GET("/api/v1/path/special-path", func(ctx *fasthttp.RequestCtx) {
println("from GET: " + s)
})
router.PATCH("/api/v1/path/{id}", func(ctx *fasthttp.RequestCtx) {
s = ctx.UserValue("id").(string)
println("from PATCH: " + s)
})
err := fasthttp.ListenAndServe("127.0.0.1:8080", router.Handler)
if err != nil {
panic(err)
}
}
Then I make the following requests, one after another:
curl --location --request PATCH 'http://127.0.0.1:8080/api/v1/path/aaabbbcccdddzzz'
curl --location --request GET 'http://127.0.0.1:8080/api/v1/path/special-path'
The output I expect to see:
from PATCH: aaabbbcccdddzzz
from GET: aaabbbcccdddzzz
The actual output:
from PATCH: aaabbbcccdddzzz
from GET: special-pathzzz
As you can see the special-path
path part overwrites part of the aaabbbcccdddzzz
word.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.