Live data from Hacker News

Better HTTP server routing in Go 1.22

eli.thegreenplace.net

61–70 of 236 posts

Re: Better HTTP server routing in Go 1.22

#61

Go is not my main tool but I've used Gin which goes like this: router.GET("/", func(context *gin.Context) { ... } And it seems to be no different than many other languages/frameworks. Are there more examples that use the "GET /path/" way ?

Haven't seen in the wild. It's just bad way to do it.

Re: Better HTTP server routing in Go 1.22

#62
post #29
post #4

Earlier quoted context omitted.

lol no, will start the proliferation of more different abstractions over it

Not likely. Routers are so easy to write that the "different abstractions" have already been written, and are unaffected by this change to the standard library, because they don't build on the standard library, they plug in next to it. The primary utility of Go's net/http is that it is a "minimal framework" that provides a fairly common plug-level compatibility between various bits and pieces. The particular bits tha…

I agree on paper, but story shown how the combination of "I like it, but I want it just a little bit different" combined with something somehow new is a recipe for new weekend projects

Re: Better HTTP server routing in Go 1.22

#63
How did this kind of syntax become so popular? I think express is the first to do the scheme of:

    app.handleGet("/route/goes/here", (req, res) => {

    });
Which seems like it's useful for making really quick and dirty micro-services (nano-services, even), but I still vastly prefer the more declarative and modular schemes of bootstrap or asp.net:

    // Middleware automatically routes "/Foo" to FooController
    [Controller]
    public class FooController : Controller
    {
        private IMyService _service { get; init; }
        
        // Declarative dependency injection
        FooController(IMyService service)
        {
            this._service = service;
        }

        // HTTP Method and Route are declarative
        [HttpGet("/")]
        public ActionResult GetBar([FromBody] Model myModel)
                                 // ^ automatic user input validation using reflection
        {
            this._service.create(myModel); // or whatever you need to do
            return Ok();
        }
    }
This has always seemed way more maintainable to me. Even microsoft has added the ability to do these quick and dirty HTTP routing methods along with top level statements.

Re: Better HTTP server routing in Go 1.22

#64
post #60

It seems like a very bizarre design choice, especially by an official language team, to use prefix strings instead of an enum. For example: (Http.GET, "/path") Rather than the current: ("GET /path") Odd.

It's mistake they can't fix without breaking existing code or introducing new function. But I'd prefer just a bunch of mux.GET/mux.POST/etc functions instead of that.

Oh damn, no overloading in Go, yeah that rules out the above I suppose.

Agreed on the dedicated GET/POST etc functions though.

Re: Better HTTP server routing in Go 1.22

#65

How did this kind of syntax become so popular? I think express is the first to do the scheme of: app.handleGet("/route/goes/here", (req, res) => { }); Which seems like it's useful for making really quick and dirty micro-services (nano-services, even), but I still vastly prefer the more declarative and modular schemes of bootstrap or asp.net: // Middleware automatically routes "/Foo" to FooController [Controller] publ…

> This has always seemed way more maintainable to me. Even microsoft has added the ability to do these quick and dirty HTTP routing methods along with top level statements.

Many people (myself included) hate decorators. Keep my code declarative and free of black magic, please. This pattern also conflates class structure with route structure. What if I wanted to assign a method in this class to another base route? You end up with routing strewn all over the application.

Re: Better HTTP server routing in Go 1.22

#66

How did this kind of syntax become so popular? I think express is the first to do the scheme of: app.handleGet("/route/goes/here", (req, res) => { }); Which seems like it's useful for making really quick and dirty micro-services (nano-services, even), but I still vastly prefer the more declarative and modular schemes of bootstrap or asp.net: // Middleware automatically routes "/Foo" to FooController [Controller] publ…

> This has always seemed way more maintainable to me. Even microsoft has added the ability to do these quick and dirty HTTP routing methods along with top level statements. Many people (myself included) hate decorators. Keep my code declarative and free of black magic, please. This pattern also conflates class structure with route structure. What if I wanted to assign a method in this class to another base route? You…

There's nothing "black magic" about them; they're very well documented features in Java, C#, and Python. They're officially experimental in Typescript but they're so heavily relied upon I can't imagine them getting deprecated

Re: Better HTTP server routing in Go 1.22

#67

Forcing a panic when 2 routes are matched seems counter intuitive to me (versus, idk, every other web framework which uses the first-to-be-registered route that matches). Are there go-specific reasons for that? The edge case of "you might register HTTP routes in a bunch of places and it's harder to find that if multiple routes match" seems like something that be worked around with tooling. I've (ab)used the behavior…

I'll always take a footgun with a sizable bang over a sinister undefined behavior.

Debugging the latter one is much more harder.

Re: Better HTTP server routing in Go 1.22

#68
post #10

Forcing a panic when 2 routes are matched seems counter intuitive to me (versus, idk, every other web framework which uses the first-to-be-registered route that matches). Are there go-specific reasons for that? The edge case of "you might register HTTP routes in a bunch of places and it's harder to find that if multiple routes match" seems like something that be worked around with tooling. I've (ab)used the behavior…

I believe it allows `/foo/bar` and `/foo/{id}` as the first one is more specific and has precedence. This looks fine to me. Looks like it will panic in case you have `/foo/{id}/delete` and `/foo/bar/{action}`. /foo/bar/delete will match both, none is more specific so it panics. Feels reasonable. Having a first one wins precedence might be better though.

The least surprising behavior would be matching `/boo/bar/{action}`, since we're dealing with path element separated by slashes, and the precedence case already exists otherwise.

Re: Better HTTP server routing in Go 1.22

#69
I wonder if the new version takes the opportunity to make the muxer faster. I needed a path matcher / muxer and I settled on forking julienschmidt/httprouter [1] into my own project, pathmatcher [2]. What I like about the original it is that it uses a trie for mapping paths to handlers, which can look up routes very quickly [3], and is optimized for low/zero allocations. My changes generalizes it (the 'handler' value can be any generic type) and exposes the underlying data structure so you can do non-http.Handler things with it if you want.

[1]: https://github.com/julienschmidt/httprouter

[2]: https://github.com/infogulch/pathmatcher

[3]: https://github.com/julienschmidt/go-http-routing-benchmark

Re: Better HTTP server routing in Go 1.22

#70

Earlier quoted context omitted.

> This has always seemed way more maintainable to me. Even microsoft has added the ability to do these quick and dirty HTTP routing methods along with top level statements. Many people (myself included) hate decorators. Keep my code declarative and free of black magic, please. This pattern also conflates class structure with route structure. What if I wanted to assign a method in this class to another base route? You…

There's nothing "black magic" about them; they're very well documented features in Java, C#, and Python. They're officially experimental in Typescript but they're so heavily relied upon I can't imagine them getting deprecated

>There's nothing "black magic" about them; they're very well documented features in Java, C#, and Python.

Sure there is. It's metaprogramming. Anyone in the world who can read code can understand this immediately:

  app.get('/', (req, res) => {
    res.send('hello world')
  })
Throw decorators in the mix, and now I need to learn exactly what this specific environment is doing with those annotations. I have absolutely no way of understanding it at a glance. And you're now also stuck with vendor lockin to whatever framework/compiler was using them, and your code can no longer be fully isolated and unit tested without the framework.
Post reply on HN