goji / goji Goto Github PK
View Code? Open in Web Editor NEWGoji is a minimalistic and flexible HTTP request multiplexer for Go (golang)
Home Page: https://goji.io
License: MIT License
Goji is a minimalistic and flexible HTTP request multiplexer for Go (golang)
Home Page: https://goji.io
License: MIT License
We're using glide for dependency management and would like to have a semver to use in our glide.yaml.
Could you please tag master with the 1.7+ context changes with 2.0 or something?
I'm getting an error when trying to go get
this repo.
$ go get -u github.com/goji/goji
package github.com/goji/goji
imports goji.io/internal: use of internal package not allowed
Any thoughts on how to deal with this? Am I getting the wrong path or package? Is the repo. go get
-able at this point?
Our CI suite broke today because of an issue that appears to be related to goji.io and it's import configuration.
From glide: https://travis-ci.org/stellar/go/jobs/214654596
[WARN] Unable to checkout goji.io
[ERROR] Update failed for goji.io: Cannot detect VCS
[INFO] --> Fetching golang.org/x/crypto.
[INFO] --> Fetching golang.org/x/net.
[INFO] --> Fetching golang.org/x/sys.
[INFO] --> Fetching gopkg.in/gavv/httpexpect.v1.
[INFO] --> Fetching gopkg.in/tylerb/graceful.v1.
[ERROR] Failed to install: Cannot detect VCS
From gb: https://travis-ci.org/stellar/horizon/jobs/214687970
FATAL: command "restore" failed: could not process dependency: unable to determine remote metadata protocol: failed to access url "https://goji.io?go-get=1"
FATAL: command "vendor" failed: exit status 1
Please advise. Thanks!
Golang/src/github.com/goji/goji/dispatch.go:6:2: use of internal package not allowed
this happened when i try to download goji package
I have a piece of JS code that does the following:
var a = Object.assign({}, state, {
isAuthenticating: false,
});
where state
is an empty object, and even though it runs fine in the browser when bundled, it fails running that same bundle in goji with the following error:
TypeError: Object has no member 'assign'
Is there any way to list all registered routes within a Mux? This is useful for debugging purposes to ensure everything as it seems, and I'd like to work on some route auto-generation tools. I understand if this isn't feasible, but it'd definitely be nice to have!
I'd like to push https://github.com/elithrar/goji-logger to goji/logger
.
i'm sorry. this is a wrong issue.
Hi,
I'm updating my app and trying to port a bit of route matching in a middleware from zenazn/goji to goji/goji. I can't get the new pattern.Match(ctx, r)
to match in the same way as the older pattern.Match(r, c)
. I was wondering if you know why this doesn't work?
gojipatterntest.txt
Output:
no match.. no match.. no match..
zenazngojipatterntest.txt
Output:
no match.. no match.. match!
Just to clarify, the results from example zenazngojipatterntest is what I'm expecting, with a match on /hello/:name
. The example gojipatterntest doesn't match this, am I missing something?
as the title says.
(love the project, by the way. thanks for working on it!)
Hi,
I am trying to set up a new project. I am not able to run "hello world" program.
Initially,
go build
exits with error
vendor/goji.io/internal/http.go:6:2: cannot find package "golang.org/x/net/context" in any of:
/workspace/src/sengkathir/vendor/golang.org/x/net/context (vendor tree)
/usr/local/go/src/golang.org/x/net/context (from $GOROOT)
/workspace/src/golang.org/x/net/context (from $GOPATH)
Upon installing context
package, again go build
exists with
./main.go:12: cannot use r (type *http.Request) as type "sengkathir/vendor/golang.org/x/net/context".Context in argument to pat.Param:
*http.Request does not implement "sengkathir/vendor/golang.org/x/net/context".Context (missing Deadline method)
$ go version
go version go1.7.3 darwin/amd64
goji version
- package: goji.io
version: v1.0
Am I missing something?
Thanks!
Hi there!
I've knocked together some simple middleware engine: https://github.com/andviro/noodle. Perhaps it would be beneficial for both projects if goji will adopt noodle.Handler - like signature, i.e. func(context.Context, http.ResponseWriter, *http.Request) error.
Rationale for error return value:
Best regards,
Andrew.
Carl! My favorite Carl!
I set out to use goji in a project recently, and, seeing that there's a v2.0.1, added require goji.io/v2 v2.0.1
to my go.mod. However, I encountered two problems with this:
v2.0.1
git tag just has module goji.io
, andIt seems like you're still treating the project as effectively v1, but go is expecting the git tags to be authoritative. So it resolves to either goji.io v2.0.0+incompatible
or goji.io v0.0.0-20181111194536-9a575ab427c3
. I suggest either removing the v2.x tags or releasing v2 fully.
<3, thanks.
When using a SubMux() sub router, I am forced to use a trailing slash on the end of the URL. For instance, given the following:
foo := goji.SubMux()
root.HandleC(pat.New("/foo/*"), foo)
foo.HandleFuncC(pat.Get("/"), getAllFoos)
foo.HandleFuncC(pat.Get("/:fooID"), getSingleFoo)
I have to use /foo/
instead of /foo
which returns a 404. I have read zenazn/goji#97 and am sold on the idea that /foo and /foo/ should be treated as 2 different URLs. But in my case I'd rather have /foo be the canonical one, and /foo/ return a 404, or maybe a 301 permanent redirect to /foo.
For a public facing Rest API I believe users (developers) are more likely to accidentally omit the slash, and while I could 301 redirect /foo to /foo/ with middleware, I'm not sure how this would play with badly coded clients that don't auto follow redirects, or the extra overhead of the redirect happening for every request.
I know it's a small thing and I can live with it. It's just one small annoyance in an otherwise perfect http request multiplexer. Keep up the excellent work :-)
So of course I could just not use SubMux and declare all the URLs on the root router, but then I lose the benefits of sub router specific middleware. I could also have /foo 301 permanent redirect to /foo/ which is what I'm currently doing.
Hi, I haven't updated in a while and notice that now you use google's context object instead of web.C, is there documentation on how to upgrade?
I know that by default if a match isn't found within Goji, http.NotFound is called. How do you recommend handling this case with a custom handler? It looks like I could potentially use a route, but I'm not sure there is a guarantee about route matching order? Thanks!
@zenazn - is there still a plan to break the API?
mux.HandleC/HandleFuncC
be kept?mux.Handle/HandleFunc
?Use/UseC
?I'm for breaking it—Goji v2 is fairly new and has lived in the world of vendoring, which makes it more likely (but not guaranteed!) that users who care have vendored the package. It would also reduce the API, which is a plus.
I love logging which states which URL/resource has been accessed for each request. It's kind of gone with the goji/goji.
How to re-enable it?
Can i get the wild card match as a parameter e.g. if i did mux.HandleFuncC("/*", myhandler). Can i do it as mux.HandleFuncC("/*param", myhandler). Can I get the parameter param from the context later
Is there any chance it will be implemented? I see some occurrences of Hijacker in the old goji, but not in the new one; so I failed to establish a WebSocket connection from the goji's endpoint.
I'd like to have a new repo created under goji called "goji/gojiid"
This repo will contain what's currently in: https://github.com/atlassian/gojiid
The project is "Goji Id", which provides a flexible middleware that puts a requestId in the http Context by either pulling it out of the http request header using custom provided keys, or generating it.
There is a default generator, or a custom generator may be provided.
Finally, it provides a function to pull the id out of the context. This function can be passed to other middleware that needs the requestId. (see: atlassian/glogrus@69a9fbb)
Is there a rate limit middle ware available?
Not sure what is going wrong here, but your links aren't working for: https://godoc.org/goji.io :(
During go get
I get an error message:
/go/src/github.com/goji/goji/dispatch.go:6:2: use of internal package not allowed
- which exits go get
with error code, however the source code is still downloaded & usable in my programs.
This however makes creating Makefile dependency-fulfilling rules impossible, along with creating CI scripts that would require all the commands to return no-error code.
I run bench from https://github.com/theckman/go-http-routing-benchmark/tree/make_it_work
and it give me bad result, why performance lower?
go version go1.7.1 darwin/amd64
Gin: 52464 Bytes
Goji: 86088 Bytes
Gojiv2: 144392 Bytes
Gin: 3856 Bytes
Goji: 2912 Bytes
Gojiv2: 7376 Bytes
Gin: 6816 Bytes
Goji: 5232 Bytes
Gojiv2: 14464 Bytes
Gin: 30400 Bytes
Goji: 27200 Bytes
Gojiv2: 104464 Bytes
test.txt
According to https://github.com/goji/goji/blob/aab2e9b11766fa8810476ef36627c004ddfbaa5a/pat/methods.go pat
at the moment supports:
In some use cases you might want to use methods other than these (e.g. lock/unlock methods from RFC 2518), which at the moment as far as I know is not feasible to be implemented in goji.
I'd propose considering newWithMethods publically accessible via making it NewWithMethods
, so you can do things like
mux.HandleFunc(NewWithMethods("/:name", "LOCK"), handlerFunc)
Please let me know what you think (I'm also more than happy to contribute to goji)
kovirolik@castle ~ $ go get goji.io
package context: unrecognized import path "context"
Hello, I wanted to try to package to compare it against "zenazn/goji" but the import paths are set to
"goji.io" instead of "github.com/goji/goji" .
Is there an spicific reason for this?
BTW : Thanks for your time and effort
Hi,
I have a question about this package. I've looked through the README and godoc.org (for the original version) and couldn't find a conclusive answer.
Suppose I have a web project that separates the frontend code (including display stuff, html, css, and http request routing and handling) from the backend service implementation (expressed as a Go interface, implemented by some concrete type).
In some situations I'd like to be able to generate URLs to frontend resources from the backend.
Is it possible to reuse the router for that purpose? For example, suppose I want to generate a relative URL to the "hello" resource named "foobar".
Can I do that in some way using the router? For example, maybe:
var url *url.URL = something ... router.HelloRoute ... {router.HelloRoute.Name: "foobar"} ...
fmt.Println(url.String())
// Output:
// /hello/foobar
Is this supported right now, and if not, is it support planned? Or do you see a better way to resolve the scenario I described above.
My goal is to avoid duplicating the routing logic in the frontend and backend, so that changing the hello route from /hello/:name
to /hi/:name
should only have to be done in one place, and it'd affect both frontend and backend.
Thanks! I like the other decisions made by this library, like keeping it simple, using context.Context
, etc.
Is this incarnation of Goji going to grow the ability to match URLs using regular expressions?
I try
params := r.Context().Value(pattern.AllVariables).(map[string]string)
but get error
imports github.com/goji/goji/pattern
imports goji.io/internal: use of internal package not allowed
there is another way?
@zenazn
So while I was messing with a logging middleware, I was printing out middleware.Pattern(ctx) in the log as the url that was hit, but when this is set on the root mux and you have a sub-mux, you'll never get the right pattern.
example:
root := goji.NewMux()
users := goji.SubMux()
//setup logging at the root mux
root.UseC(NewLoggerMiddleware())
root.HandleFunc(pat.Get("/my-app"), IndexHandler)
root.Handle(pat.Get("/my-app/*"), subRouter)
subRouter.HandleFuncC(pat.Get("/some-route"),SomeHandler)
// logging middleware does something like this:
fmt.Println(middleware.Pattern(ctx)
When you call /my-app, the log prints "/my-app". that's fine
But when you hit /my-app/some-route" the log will always print "/my-app/*". This is because the logger was added on the root mux and that's the pattern that was matched on the root mux. That makes sense.
Unfortunately, If I also add the logger to the sub-mux, I'll get 2 log entries for every request, which is not what I want.
I should be able to do:
subRouter.Abandon(root.NewLoggerMiddleware)
subRouter.UseC(NewLoggerMiddleware)
So, some of the time I have middleware that's truly global and I don't care if it runs on the root context, but other times, I want to have a "sepecial" instance of the middleware for a sub-mux that overrides the instance on the root mux
go get goji.io
go get github.com/stretchr/testify
sample code[main.go]
package main
import (
"fmt"
"net/http"
"goji.io"
"goji.io/pat"
)
func hello(w http.ResponseWriter, r *http.Request) {
name := pat.Param(r, "name")
fmt.Fprintf(w, "Hello, %s!", name)
}
func main() {
mux := goji.NewMux()
mux.HandleFunc(pat.Get("/hello/:name"), hello)
http.ListenAndServe("localhost:8000", mux)
}
test code[main_test.go]
package main
import (
"net/http"
"testing"
"net/http/httptest"
"github.com/stretchr/testify/assert"
)
func TestHello(t *testing.T) {
t.Run("hello", func(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(hello))
defer s.Close()
res, err := http.Get(s.URL)
assert.NoError(t, err)
defer res.Body.Close()
})
}
result
(go:test-go) [vagrant@localhost src]$ go test
2017/03/22 09:02:54 http: panic serving 127.0.0.1:48024: interface conversion: interface is nil, not string
goroutine 11 [running]:
net/http.(*conn).serve.func1(0xc42008e600)
/home/vagrant/.gvm/gos/go1.7.4/src/net/http/server.go:1491 +0x12a
panic(0x66ae40, 0xc4200e8280)
/home/vagrant/.gvm/gos/go1.7.4/src/runtime/panic.go:458 +0x243
goji.io/pat.Param(0xc4200d41e0, 0x6b49d3, 0x4, 0x0, 0xc4200707c0)
/home/vagrant/workspace/test-go/src/goji.io/pat/pat.go:301 +0xe6
_/home/vagrant/workspace/test-go/src.hello(0x7d0cc0, 0xc4200fa000, 0xc4200d41e0)
/home/vagrant/workspace/test-go/src/main.go:10 +0x47
net/http.HandlerFunc.ServeHTTP(0x6d8618, 0x7d0cc0, 0xc4200fa000, 0xc4200d41e0)
/home/vagrant/.gvm/gos/go1.7.4/src/net/http/server.go:1726 +0x44
net/http.serverHandler.ServeHTTP(0xc42008e400, 0x7d0cc0, 0xc4200fa000, 0xc4200d41e0)
/home/vagrant/.gvm/gos/go1.7.4/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc42008e600, 0x7d1280, 0xc42001cb00)
/home/vagrant/.gvm/gos/go1.7.4/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
/home/vagrant/.gvm/gos/go1.7.4/src/net/http/server.go:2293 +0x44d
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x48 pc=0x47689c]
goroutine 6 [running]:
panic(0x6693c0, 0xc42000c0d0)
/home/vagrant/.gvm/gos/go1.7.4/src/runtime/panic.go:500 +0x1a1
testing.tRunner.func1(0xc42008c240)
/home/vagrant/.gvm/gos/go1.7.4/src/testing/testing.go:579 +0x25d
panic(0x6693c0, 0xc42000c0d0)
/home/vagrant/.gvm/gos/go1.7.4/src/runtime/panic.go:458 +0x243
_/home/vagrant/workspace/test-go/src.TestHello.func1(0xc42008c240)
/home/vagrant/workspace/test-go/src/main_test.go:16 +0xec
testing.tRunner(0xc42008c240, 0x6d8608)
/home/vagrant/.gvm/gos/go1.7.4/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
/home/vagrant/.gvm/gos/go1.7.4/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL _/home/vagrant/workspace/test-go/src 0.010s
error is the same.
res, err := http.Get(s.URL + "/hello/test")
Thanks!!
I want to be able to log the entire pattern that was matched in a middleware but this doesn't seem easily doable if I am using submuxes.
If I put the middleware on the root mux then I only get the pattern up to the wildcard. If I put the middleware on the submux then I get the pattern after the wildcard.
Ideally I would like to be able to put it on the root mux and get the whole pattern, but I would settle for doing it on each submux as well.
Do you have advice for how to do this? Thanks.
Consider this a tracking issue for adding an examples
directory or (better) some examples on the website.
context.Context
between handlers.I'd be happy to contribute here, but wanted to open this up for discussion first, and for others who might have more time to chip in.
the new go modules allow to fetch versions with go get.
but this does not seem to work:
go get [email protected]
go get [email protected]: no matching versions for query "v1.1"
Example:
mux := goji.NewMux()
mux.UseC(middlewareThatChangesRequestPostToPut)
mux.HandleC(pat.Put("/somepath"), someHandler)
I was surprised to find that writing middleware to change the request.Method from POST to PUT would not effect the route pattern matcher on line 3. Looking at the source comments, it seems that routes are parsed before middleware is run. Is there a reason for that?
To get this to work properly, I'll need to wrap the mux itself...
mux := goji.NewMux()
mux.HandleC(pat.Put("/somepath"), someHandler)
http.Handle("/", middlewareThatChangesRequestPostToPut(mux))
As middleware is added to the mux, I think the natural assumption is that it is going to affect all middleware and handlers lower in the stack. Is there any interest in having this changed?
Suppose you have an endpoint pat.Get("/foo")
and the user/client does an http.Post(".../foo")
. They will get a 404 not found, but they "really" should get a 400/bad method. Is there a way to make Goji produce "dummy" routes that respond with bad method for every HTTP verb that isn't implemented for a particular endpoint on a mux?
Trying to handle 404 error as described here in #20, but find out that middleware.Handler(rq.Context()) returns nil even if route is found.
Complete example:
func TestGoji(t *testing.T) {
mux := goji.NewMux()
mux.HandleFunc(pat.Get("/hello"), func(w http.ResponseWriter, rq *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"hello": "world"})
})
mux.Use(func(next http.Handler) http.Handler {
mv := func(w http.ResponseWriter, rq *http.Request) {
h := middleware.Handler(rq.Context())
if nil == h {
log.Println("It's always nil actually")
}
next.ServeHTTP(w, rq)
}
return http.HandlerFunc(mv)
})
http.ListenAndServe(":8080", mux)
}
Hi,
Glad to see a new version of goji using context.Context (i'll drop my goji fork once this new version has gotten enough testing) !
In slim I found very convenient to be able to define middlewares using the following signature:
func(ctx context.Context, w http.ResponseWriter, r *http.Request, next goji.Handler)
While is is quite easy to write a wrapper for this, it would be nice to have this signature allowed by default since in my experience if allows to more easily write middlewares. Would you consider either adding a new method .UseM(...) or adding a conversion function ? Trivial adapter below:
type handlerNext struct {
f func(_ context.Context, _ http.ResponseWriter, _ *http.Request, next goji.Handler)
next goji.Handler
}
func (h handlerNext) ServeHTTPC(c context.Context, w http.ResponseWriter, r *http.Request) {
h.f(c, w, r, h.next)
}
// Middleware converts a func(_ context.Context, _ http.ResponseWriter, _ *http.Request, _ goji.Handler) into a goji middleware
func Middleware(f func(_ context.Context, _ http.ResponseWriter, _ *http.Request, _ goji.Handler)) func(goji.Handler) goji.Handler {
return func(h goji.Handler) goji.Handler {
return handlerNext{f, h}
}
}
Thanks for reading this !
Hi!
can not use to GAE?
go-app-builder: Failed parsing input: parser: bad import "syscall" in vendor/golang.org/x/net/internal/nettest/rlimit_unix.go
I think had been used before ?
Using the go17
branch and running the example code from the README, I get a panic:
2016/09/02 12:37:34 http: panic serving 127.0.0.1:58164: interface conversion: interface is nil, not string
goroutine 6 [running]:
net/http.(*conn).serve.func1(0xc42005e400)
/opt/go/src/net/http/server.go:1491 +0x12a
panic(0x6422e0, 0xc4200184c0)
/opt/go/src/runtime/panic.go:458 +0x243
goji.io/pat.Param(0x7911c0, 0xc420015710, 0x687908, 0x4, 0x78dd40, 0x6a8a68)
/opt/src/goji.io/pat/pat.go:303 +0xca
main.hello(0x790a00, 0xc420057ba0, 0xc4200b45a0)
/opt/src/github.com/moorereason/gojitest/main.go:13 +0x63
net/http.HandlerFunc.ServeHTTP(0x6a8a68, 0x790a00, 0xc420057ba0, 0xc4200b45a0)
/opt/go/src/net/http/server.go:1726 +0x44
goji%2eio.dispatch.ServeHTTP(0x790a00, 0xc420057ba0, 0xc4200b45a0)
/opt/src/goji.io/dispatch.go:17 +0xd6
goji%2eio.(*dispatch).ServeHTTP(0x7c7de8, 0x790a00, 0xc420057ba0, 0xc4200b45a0)
<autogenerated>:1 +0x6a
goji%2eio.(*Mux).ServeHTTP(0xc42005e200, 0x790a00, 0xc420057ba0, 0xc4200b45a0)
/opt/src/goji.io/mux.go:74 +0x16b
net/http.serverHandler.ServeHTTP(0xc42005e380, 0x790a00, 0xc420057ba0, 0xc4200b42d0)
/opt/go/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc42005e400, 0x790f80, 0xc420018400)
/opt/go/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
/opt/go/src/net/http/server.go:2293 +0x44d
Offending line from main.go:
name := pat.Param(ctx, "name")
It's not easily catchable (or at least I haven't read how). Easier was editing Param to return "" if the context interface was nil. I can submit a push request, but haven't ever written a test, so will have to figure that out first.
I'm not sure what the version support targets are, but it appears that net/url:URL EscapedPath()
is not present in go1.4 which is used by AppEngine. I'd be happy to work on a PR if you'd like.
Hi @zenazn,
As context pkg landed in standard library of go1.7 tip, you may need to revisit stability section of README file before it wide spread!
Just curious, any specific advantage for changing syntax in new goji
from simple:
goji.Get("/hello/:name", hello)
to verbose pat.Get(...):
mux.HandleFuncC(pat.Get("/hello/:name"), hello)
Some how, i got addicted to your old syntax! Thanks for the great library.
Hi there,
What's the recommended way for handling application panics, in order to serve a 500 error page?
i'm sorry. this is a wrong issue.
The "notFound Handler" was a neat convenience in zenazn/goji
https://github.com/goji/goji/blob/master/router_trie.go doesn't seem to have a similar concept - probably because you decided to make less assumptions in goji2
I'm wondering what would be the best way to implement a custom 404 handler with goji2
thanks for new libs
I'd like to have anew repo under goji created called "goji/glogrus2"
This is a port of the original glogrus project to goji2
The contents of this repo should contain what's in this branch:
https://github.com/atlassian/glogrus/tree/goji2
Not only does this include the update to goji2, but it also provides a pluggable way to retrieve requestId from the http Context. see: https://github.com/atlassian/gojiid
For more info on why I'm requesting this repo, see: goji/glogrus#2
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.