Live data from Hacker News

Better HTTP server routing in Go 1.22

eli.thegreenplace.net

211–220 of 236 posts

Re: Better HTTP server routing in Go 1.22

#211
post #109
post #3

As I commented[1] I think the syntax is flawed in the proposal. You need to weirdly create a magic string to define your handler. Why not make it an actual argument, then using already existing constants is easier. [1] https://github.com/golang/go/issues/61410#issuecomment-16580...

That was my gut feeling as well, but honestly when using Gin, having methods like .Get(), .Post() etc. has never solved anything for me. Having a single registration method with the method in the string is probably 100% fine.

"probably" is key Here. this introduces the possibility of typo erros that can even be discovered late. Now you will need a Vet check to make sure that GET, POST etc are written correctly instead of letting the compiler to do it's job. .Get(), Post() get compiler guarantees that they are sending the right Method string.

Re: Better HTTP server routing in Go 1.22

#212
post #79

Earlier quoted context omitted.

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

> // Middleware automatically routes "/Foo" to FooController I don't know why, but I truly do not like this. So if I create a "HelloController" class does the middleware just start automatically routing "/hello" to it?

ASP.NET Core can easily route "/hello" to HelloController.Index(), but it's not exactly automatic. The controller library adds routes to the routing middleware in a call to MapControllerRoute the app developer must make during startup which specifies a pattern.

    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
https://learn.microsoft.com/en-us/aspnet/core/mvc/controller...

If you don't call one of the MapController methods, requests will not be routed to controllers even if they exist in the same project.

Re: Better HTTP server routing in Go 1.22

#213

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…

This comment is interesting to me, because in Clojure there is a data-driven routing library called Reitit, and by default it will refuse to compile conflicting routes unless you explicitly tag the conflicting routes as conflicting. So Golang's new behavior is more intuitive to me than the current behavior.

I have also ran into situations where I needed a routing tree like

  [["/foo/bar"]
   ["/foo/:id"]]
but it's better IMO for routing libraries to force the user to acknowledge they are introducing conflicting routes rather than silently resolve conflicts. That way the user is forced to understand the behavior of the router.

Re: Better HTTP server routing in Go 1.22

#214

Earlier quoted context omitted.

What's wrong with automatically registering a HEAD route?

"The HTTP HEAD method requests the headers that would be returned if the HEAD request's URL was instead requested with the HTTP GET method. ". So it goes against the HTTP spec.

How does it go against the HTTP Spec. The HEAD method could be autoregistered for all handlers of GET Requests and library makes sure no body is sent (Basically it's a autoregistered middleware that wraps the get handler and overwrites the reponse writer with an empty body.)

Arguably this is more correct that letting the users declare a separate Handler that can neither guarantee the same headers as the the GET Handler not guarantee that the body is not sent the response.

Re: Better HTTP server routing in Go 1.22

#215
post #13

Earlier quoted context omitted.

> Are there go-specific reasons for that? In general , the reason you use a compiled / typed language like golang at all (instead of, say, perl) is to "left shift" your bugs: A bug caught when you first spin up your application is better than a bug caught after a corner case acts up in the wild, and a bug caught when you compile is better than a bug caught when you first spin up your application. I recently ran a cro…

Wouldn’t the “left-shift” be a compiler error instead of a panic?

It can not be decided on compile time but it provides the basis for a build time "error". It's enough to have a testcase that registers your routes and the bug is descovered even before you commit potentially.

Re: Better HTTP server routing in Go 1.22

#216
post #205

Earlier quoted context omitted.

This seems like an issue caused by registration at a distance. I'm new to go and it is one of the things that felt most wrong. I'm used to a router where you define a big list of routes all in one place, maybe in some DSL. That's very easy to refactor, and doesn't have any ambiguity. If a library wants a route registered it puts a snippet in the docs for users to copy. Go in general seems to value clarity over magic…

How is this new to Go? Almost all Java frameworks that rely on Annotations do registration at a distance. Controllers are Routinely declared on different packages and even injected from dependency libraries.

I agree with most of this post. The one exception in my experience: Vertx. I never saw any annotations for routing. It is a very verbose library, but that means there is no black magic.

Re: Better HTTP server routing in Go 1.22

#217
post #185

Earlier quoted context omitted.

It doesn't feel to me like much of a gain over having said team expose a specific default self registration function. Then that act can be explicit rather than action at a distance on some dependency defined global state. I think this pattern in the standard library is a mistake.

Yeah, the trade-off is literally: import _ "thing" Vs: import "thing" thing.Register() But one uses a strange construct to save a single line, loses the ability to control order, and encourages people to use globals that they can't control.

thing.Register() may register a route that conflicts with yours and it will never be matched in this case if declaration order was taken into account. You may discover this too late when you either have missed important calls on that thing or when requests intended for that thing are causing unintended effects on your first declared route.

Re: Better HTTP server routing in Go 1.22

#218
post #185

Earlier quoted context omitted.

It doesn't feel to me like much of a gain over having said team expose a specific default self registration function. Then that act can be explicit rather than action at a distance on some dependency defined global state. I think this pattern in the standard library is a mistake.

Yeah, the trade-off is literally: import _ "thing" Vs: import "thing" thing.Register() But one uses a strange construct to save a single line, loses the ability to control order, and encourages people to use globals that they can't control.

I very much dislike import side effects in any language. Im a lot happier where thing.Register() is still forced to happen in the main function.

Still, I can understand it for some components like loggers to not add boiler plate to every library. However, I was very uneasy to see that enabling gzip decompression in a gRPC server is done through a magic _ import. You have to initialize the server anyways, so why not just make it an explicit function argument?

Re: Better HTTP server routing in Go 1.22

#219

I don't like this. Is there a reason for using a stringified method prefix? I'd prefer the type safety of verb-specific methods (i.e. mux.Get, mux.Post etc) than magic strings validated at run time. Additionally editors can autocomplete/intellisense methods.

Not a fan either. I want to be sure that routing is going to work at compile time, not at runtime.

how about build time? just add a test and the "runtime" become build time.

Re: Better HTTP server routing in Go 1.22

#220

I don't like this. Is there a reason for using a stringified method prefix? I'd prefer the type safety of verb-specific methods (i.e. mux.Get, mux.Post etc) than magic strings validated at run time. Additionally editors can autocomplete/intellisense methods.

I also don't prefer using strings, but to be fair, HTTP methods are just strings when the request is received. There is some beauty in that in matches the prefix of the first line of an HTTP packet

Strings with a well defined meaning that is not being taken into consideration here beyond routing.
Post reply on HN