Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 4113

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T08:59:07+00:00 2024-11-26T08:59:07+00:00

Showcasing higher order functions with HTTP router

  • 61k

The other day I was talking to a friend who was deep in the woods reworking a piece of software. There was a global map involved, where the keys are HTTP routes and values are functions. Plugins would add their routes to the map by assigning a function reference. Then a core setup function would register all routes from the map with the actual HTTP router. The purpose for the map wasn't quite clear to me and the friend told me some plugins conflict with each other (e.g. login with Google vs login with Microsoft). A core setup function would decide which of the conflicting plugins actually to use.

Maybe there's an alternative to the global map. Just let the plugins add their routes directly to the router! But what about the setup function discriminating on arbitrary conditions? Let the plugins decide for themselves! Enter higher order functions, which are defined as functions taking function type arguments or returning function types.

Registering routes without direct router dependency

To add routes, assume we have a nifty library providing a router struct.

func (a *NiftyRouter) Register(method, path string, handler func()) 
Enter fullscreen mode Exit fullscreen mode

On the other hand there's a bunch of plugin functions eager to add routes. To avoid strongly coupling plugins and the concrete router struct, let's define a function type that expresses the intent of registering a route:

type RegisterRouteFunc func(method, path string, handler func()) 
Enter fullscreen mode Exit fullscreen mode

An implementation using the concrete router struct is a higher order function returning a function matching RegisterRouteFunc signature:

func RegisterRouteNifty(router *NiftyRouter) RegisterRouteFunc {     return func(method, path string, handler func()) {         router.Register(method, path, handler)     } } 
Enter fullscreen mode Exit fullscreen mode

Notice how the router argument is used in the returned function, creating a closure. The performance penalty of closure creation is negligible because RegisterRouteNifty is called only once early in program runtime (more on that later).

Defining the plugin interface

In the same vein, create a function type for the intent of adding a plugin. The function receives an argument of RegisterRouteFunc, conveying the fact that plugins can register HTTP routes.

type AddPluginFunc func(register RegisterRouteFunc) 
Enter fullscreen mode Exit fullscreen mode

Each plugin provides an implementation of AddPluginFunc:

func AddProfilePagePlugin() AddPluginFunc {     return func(register RegisterRouteFunc) {         register("GET", "/profile", func() {             // ...         })     } } 
Enter fullscreen mode Exit fullscreen mode

If there's some need for arbitrary conditions, add the required inputs as arguments to the named function. This creates another closure, but again the impact is negligible.

func AddGoogleLoginPlugin(config *Configuration) AddPluginFunc {     return func(register RegisterRouteFunc) {         if (config.Foo) {             register(/* ... */)         }     } } 
Enter fullscreen mode Exit fullscreen mode

There might also be a AddPluginFunc function that composes several AddPluginFuncs into one function:

func AddPlugins(plugins ...AddPluginFunc) AddPluginFunc {     return func(register RegisterRouterFunc) {         for _, f := range plugins {             f(register)         }     } } 
Enter fullscreen mode Exit fullscreen mode

Putting it together

With the building blocks in place, the main function can be assembled:

func main() {     // Some requirements     var config *Configuration     var router *NiftyRouter      register := RegisterRouteNifty(router)      AddPlugins(         AddGoogleLoginPlugin(config),         AddMicrosoftLoginPlugin(config),         AddProfilePagePlugin(),         // ...     )(register)      // Start the router... } 
Enter fullscreen mode Exit fullscreen mode

Of course, higher order functions can be used in many different circumstances. Some care has to be taken when creating closures to avoid performance penalties.

(The code examples were all written for this post.)

functionalgotutorialwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.