Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: cleaner routing using gorilla mux regexps #185

Merged
merged 12 commits into from
Oct 20, 2024

Conversation

samlaf
Copy link
Collaborator

@samlaf samlaf commented Oct 14, 2024

This is still WIP, only refactored the GET methods so far, and still having trouble adapting the tests. But curious for opinions/criticisms at this point.

Fixes Issue

Fixes #

Changes proposed

Our routing is a bit convoluted and hard to follow. I'm working on an openapi spec in #181, which we could use with tests to enforce our actual golang router implements exactly. But our code is hard to read because the logic for the 3 types of commitments (simple, op generic, op keccak) is sprinkled all throughout different helper functions. Typically it's better to push ifs up and fors down.

go1.22's revamped the stdlib router, but still doesn't have prefix or regexp abilities, which is why I opted to using gorilla mux, which is a minimal (in the sense that it's not an entire web framework we are taking on), but still very extensive routing library. In my opinion routing paths should be easy to read like openapi specs, not be sprinkled throughout if statements left and write inside helper functions. This PR makes routes like:
image

Screenshots (Optional)

Note to reviewers

@samlaf samlaf marked this pull request as draft October 14, 2024 13:29
@samlaf samlaf force-pushed the refactor--better-routing-using-gorilla-mux-patterns branch from aaad46a to cf11d90 Compare October 15, 2024 16:03
@samlaf samlaf marked this pull request as ready for review October 15, 2024 22:46
server/middleware.go Show resolved Hide resolved
server/middleware.go Outdated Show resolved Hide resolved
Comment on lines 12 to 18
subrouterGET := r.Methods("GET").PathPrefix("/get").Subrouter()
// simple commitments (for nitro)
subrouterGET.HandleFunc("/"+
"{optional_prefix:(?:0x)?}"+ // commitments can be prefixed with 0x
"{version_byte_hex:[0-9a-fA-F]{2}}"+ // should always be 0x00 for now but we let others through to return a 404
"{raw_commitment_hex:[0-9a-fA-F]*}",
withLogging(withMetrics(svr.handleGetSimpleCommitment, svr.m, commitments.SimpleCommitmentMode), svr.log),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what benefits do we reap by using the gorilla library? I.e, why use a heavy framework vs. what we had before. Generally agree with the structure of the refactoring but still a bit curious if we need to introduce a heavy framework with more developer complexity.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also from a philosophical standpoint I've never seen ethereum projects use third party frameworks like this in RPC server implementations

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I've got many mouthfuls to say about this haha:

  1. re ethereum projects not using web frameworks: not quite sure I haven't done an extensive survey. A lot of them are simple json-rpc, so they use a json-rpc library instead of a rest api framework, but the altda decided to go with rest api. Also if I had to guess I'd say if other projects that are (proxy) servers like ours (like flashbots builder say) are not using web framework either out of ignorance, or because their routing is super simple. But our routing is a bit more involved, so basic stdlib http router (even after go1.22 improvements) isn't enough.
  2. gorilla is not a heavy framework. it's actually extremely lightweight. If I had my way I would actually use a full fledged framework with middlewares, like gin or echo (note that even these are "lightweight" frameworks). But gorilla mux is purely a routing library, not a framework. See limitations section at the bottom of this for a comparison.
  3. I already tried to explain the benefits of using gorilla's router instead of stdlib's router. I think this article summarizes my thoughts regarding the problem with our current implementation better than I ever could. Basically our routing ifs/switches are sprinkled everywhere in the proxy. This makes for very difficult reading. There's really only 3 types of commitments, so we should make the choice one of which "row" we're in, at the top routing layer, and then the rest of the code should be aware of which route it's in and be able to specialize. See for eg this switch statement; don't think we should have this that far down code paths.

server/handlers.go Show resolved Hide resolved
server/handlers.go Outdated Show resolved Hide resolved
server/handlers.go Outdated Show resolved Hide resolved
@samlaf samlaf requested a review from epociask October 16, 2024 21:02

// handlePostSimpleCommitment handles the POST request for simple commitments.
func (svr *Server) handlePostSimpleCommitment(w http.ResponseWriter, r *http.Request) error {
svr.log.Info("Processing simple commitment")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we also put the method type for the simple commitment strings as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

465fb84
moved all the logs to the shared handlers (adds a redundant reencoding to hex, but at least its simpler this way)


// handlePostOPGenericCommitment handles the POST request for optimism generic commitments.
func (svr *Server) handlePostOPGenericCommitment(w http.ResponseWriter, r *http.Request) error {
svr.log.Info("Processing simple commitment")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this log stmt doesn't reflect the function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

465fb84
moved all the logs to the shared handlers (adds a redundant reencoding to hex, but at least its simpler this way)

@samlaf samlaf requested a review from epociask October 18, 2024 10:56
Copy link
Collaborator

@epociask epociask left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@samlaf samlaf merged commit 0035323 into main Oct 20, 2024
7 checks passed
@samlaf samlaf deleted the refactor--better-routing-using-gorilla-mux-patterns branch October 20, 2024 09:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants