Goji is a minimalistic and flexible HTTP request multiplexer for Go (golang)

Goji

GoDoc Build Status

Goji is a HTTP request multiplexer, similar to net/http.ServeMux. It compares incoming requests to a list of registered Patterns, and dispatches to the http.Handler that corresponds to the first matching Pattern. Goji also supports Middleware (composable shared functionality applied to every request) and uses the standard context package to store request-scoped values.

Quick Start

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

Please refer to Goji's GoDoc Documentation for a full API reference.

Stability

Goji's API was recently updated to use the new net/http and context integration, and is therefore some of its interfaces are in a state of flux. We don't expect any further changes to the API, and expect to be able to announce API stability soon. Goji is suitable for use in production.

Prior to Go 1.7, Goji promised API stability with a different API to the one that is offered today. The author broke this promise, and does not take this breach of trust lightly. While stability is obviously extremely important, the author and community have decided to follow the broader Go community in standardizing on the standard library copy of the context package.

Users of the old API can find that familiar API on the net-context branch. The author promises to maintain both the net-context branch and master for the forseeable future.

Community / Contributing

Goji maintains a mailing list, gojiberries, where you should feel welcome to ask questions about the project (no matter how simple!), to announce projects or libraries built on top of Goji, or to talk about Goji more generally. Goji's author (Carl Jackson) also loves to hear from users directly at his personal email address, which is available on his GitHub profile page.

Contributions to Goji are welcome, however please be advised that due to Goji's stability guarantees interface changes are unlikely to be accepted.

All interactions in the Goji community will be held to the high standard of the broader Go community's Code of Conduct.

Owner
Goji
Goji community contributions
Goji
Comments
  • Go 1.7 + http.Request.Context()

    Go 1.7 + http.Request.Context()

    @zenazn - is there still a plan to break the API?

    • Will mux.HandleC/HandleFuncC be kept?
    • Will they be rolled into 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.

  • NotFound Handler

    NotFound Handler

    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

  • Cannot install using glide or gb

    Cannot install using glide or gb

    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!

  • Unexpected route/middleware execution order

    Unexpected route/middleware execution order

    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?

  • Listing all routes within a Mux

    Listing all routes within a Mux

    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!

  • go modules support ?

    go modules support ?

    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"
    
  • Add Examples

    Add Examples

    Consider this a tracking issue for adding an examples directory or (better) some examples on the website.

    • [ ] Add a simple example with 2-3 routes and some template rendering. There should be some middleware involved to show how to pass values using context.Context between handlers.
    • [ ] A more complex example where Goji is an API server serializing objects to JSON. Possibly show some CORS middleware here, as this is a common use-case in a world of React, Vue, Ember, etc. BoltDB could help in making it a little more "real world" without relying on external dependencies.

    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.

  • url.URL escaped path not present in go 1.4 which AppEngine uses

    url.URL escaped path not present in go 1.4 which AppEngine uses

    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.

  • Could pat.Param not panic when it the interface is nil

    Could pat.Param not panic when it the interface is nil

    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.

  • Need to abandon middleware in sub mux

    Need to abandon middleware in sub mux

    @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

  • New Org Repo Request: goji/logger

    New Org Repo Request: goji/logger

    I'd like to push https://github.com/elithrar/goji-logger to goji/logger.

    • Ports the Goji v1 middleware Logger and RequestID to Goji v2
    • Makes it available (discoverable) under the organization
    • Provides a friendly screenshot of the output

    @zenazn

  • pat: remove allocation in match.Value(internal.Path) case

    pat: remove allocation in match.Value(internal.Path) case

    hi @zenazn!

    In an application I was benchmarking, about 40% of allocations per API request were from match.Value returning a string, and that return implicitly moving the string onto the heap for reference as an interface{} ( https://github.com/golang/go/blob/master/src/runtime/iface.go#L388-L396 ). I plan to separately deal with that inefficient call pattern, but it will be more involved, and removing this allocation is relatively straight forward.

    I attempted a separate approach of trying to "just" use context.WithValue instead of match, but as you might have guessed that turned out to be ... not really workable ( https://github.com/goji/goji/compare/master...bpowers:goji:use-vanilla-ctx?expand=1 for reference).

    I think the biggest thing would be a double-check on my assumption that matches are immutable, so taking a reference to an entry in the slice is safe.

    I'd also be happy to rebase this on the v3 branch if thats more palatable!

  • Is there a way to pass the regexp that was available in the old goji?

    Is there a way to pass the regexp that was available in the old goji?

    I have defined the following endpoint with https://github.com/zenazn/goji

    goji.Get(regexp.MustCompile(`^/@(?P<accountName>[a-zA-Z]+)$`), getAccountName)
    

    Can I get the same behavior with the new goji?

  • Nicer errors on requests?

    Nicer errors on requests?

    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?

  • git tags suggest v2, but go.mod disagrees

    git tags suggest v2, but go.mod disagrees

    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:

    • The go.mod at the v2.0.1 git tag just has module goji.io, and
    • The vanity URL https://goji.io/v2 404s.

    It 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.

  • Is it possible to use router in backend implementations to generate URLs to frontend resources?

    Is it possible to use router in backend implementations to generate URLs to frontend resources?

    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.

  • pat: support generating URLs from a Pattern

    pat: support generating URLs from a Pattern

    Adds support for generating paths from a Pattern and a mapping from named matches to string values. This is useful in writing API clients as it allows for constructing URLs that exactly match the routing table with semantically meaningful arguments.

Related tags
Go Server/API micro framework, HTTP request router, multiplexer, mux
Go Server/API micro framework, HTTP request router, multiplexer, mux

?? gorouter Go Server/API micro framework, HTTP request router, multiplexer, mux. ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free t

Dec 16, 2022
Lightning Fast HTTP Multiplexer
Lightning Fast HTTP Multiplexer

bone What is bone ? Bone is a lightweight and lightning fast HTTP Multiplexer for Golang. It support : URL Parameters REGEX Parameters Wildcard routes

Dec 17, 2022
Fast and flexible HTTP router
Fast and flexible HTTP router

treemux - fast and flexible HTTP router Basic example Debug logging CORS example Error handling Rate limiting using Redis Gzip compression OpenTelemet

Dec 27, 2022
FastRouter is a fast, flexible HTTP router written in Go.

FastRouter FastRouter is a fast, flexible HTTP router written in Go. FastRouter contains some customizable options, such as TrailingSlashesPolicy, Pan

Sep 27, 2022
High-speed, flexible tree-based HTTP router for Go.

httptreemux High-speed, flexible, tree-based HTTP router for Go. This is inspired by Julien Schmidt's httprouter, in that it uses a patricia tree, but

Dec 28, 2022
Go HTTP request router and web framework benchmark

Go HTTP Router Benchmark This benchmark suite aims to compare the performance of HTTP request routers for Go by implementing the routing structure of

Dec 27, 2022
A high performance HTTP request router that scales well

HttpRouter HttpRouter is a lightweight high performance HTTP request router (also called multiplexer or just mux for short) for Go. In contrast to the

Dec 28, 2022
A benchmark suite aims to compare the performance of HTTP request routers for Go

Go HTTP Router Benchmark This benchmark suite aims to compare the performance of HTTP request routers for Go by implementing the routing structure of

Oct 25, 2021
An HTTP request routing benchmark suite for Go.

Go HTTP Request Routing Benchmark An HTTP request routing benchmark suite for Go. Results goos: linux goarch: amd64 pkg: github.com/aofei/go-http-requ

Dec 14, 2021
A minimalist HTTP request routing helper for Go.

R2 A minimalist HTTP request routing helper for Go. The name "R2" stands for "Request Routing". That's all, R2 is just a capable little helper for HTT

Sep 7, 2022
A minimalist HTTP request routing helper for Go.

A minimalist HTTP request routing helper for Go.

Sep 7, 2022
A high performance HTTP request router that scales well

HttpRouter HttpRouter is a lightweight high performance HTTP request router (also called multiplexer or just mux for short) for Go. In contrast to the

Dec 9, 2021
A high performance fasthttp request router that scales well
A high performance fasthttp request router that scales well

FastHttpRouter FastHttpRouter is forked from httprouter which is a lightweight high performance HTTP request router (also called multiplexer or just m

Dec 1, 2022
Fast, simple, and lightweight HTTP router for Golang

Sariaf Fast, simple and lightweight HTTP router for golang Install go get -u github.com/majidsajadi/sariaf Features Lightweight compatible with net/ht

Aug 19, 2022
Lightweight Router for Golang using net/http standard library with custom route parsing, handler and context.

Go-Lightweight-Router Lightweight Router for Golang using net/http standard library with custom route parsing, handler and context. Further developmen

Nov 3, 2021
xujiajun/gorouter is a simple and fast HTTP router for Go. It is easy to build RESTful APIs and your web framework.

gorouter xujiajun/gorouter is a simple and fast HTTP router for Go. It is easy to build RESTful APIs and your web framework. Motivation I wanted a sim

Dec 8, 2022
Simple Golang HTTP router
Simple Golang HTTP router

Bellt Simple Golang HTTP router Bellt Package implements a request router with the aim of managing controller actions based on fixed and parameterized

Sep 27, 2022
An extremely fast Go (golang) HTTP router that supports regular expression route matching. Comes with full support for building RESTful APIs.

ozzo-routing You may consider using go-rest-api to jumpstart your new RESTful applications with ozzo-routing. Description ozzo-routing is a Go package

Dec 31, 2022
:rotating_light: Is a lightweight, fast and extensible zero allocation HTTP router for Go used to create customizable frameworks.
:rotating_light: Is a lightweight, fast and extensible zero allocation HTTP router for Go used to create customizable frameworks.

LARS LARS is a fast radix-tree based, zero allocation, HTTP router for Go. view examples. If looking for a more pure Go solution, be sure to check out

Dec 27, 2022