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

[feature]: Add ability to assign routes to variables #664

Open
bioform opened this issue Dec 1, 2024 · 4 comments
Open

[feature]: Add ability to assign routes to variables #664

bioform opened this issue Dec 1, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@bioform
Copy link

bioform commented Dec 1, 2024

It would be good to have the ability to assign routes to variables...
Something like:

huma.Get(api, "/confirm/{token}", userapi.ConfirmEmailHandler).AssignTo(&route.ConfirmEmail)

// and use it like
emailConfirmationLink := baseUrl + route.ConfirmEmail(user.EmailConfirmationToken)
SendEmailConfirmation(user.Name, emailConfirmationLink)
@bioform
Copy link
Author

bioform commented Dec 1, 2024

Even more general way:

huma.Get(api, "/confirm/{token}", userapi.ConfirmEmailHandler).AssignTo(&route.ConfirmEmail)

// and use it like
emailConfirmationLink := baseUrl + route.ConfirmEmail.Path(user.EmailConfirmationToken)
SendEmailConfirmation(user.Name, emailConfirmationLink)

// or/and
emailConfirmationLink := route.ConfirmEmail.Url(baseUrl, user.EmailConfirmationToken)
SendEmailConfirmation(user.Name, emailConfirmationLink)

@danielgtaylor danielgtaylor added the enhancement New feature or request label Dec 3, 2024
@danielgtaylor
Copy link
Owner

@bioform is this feature request mostly about rendering URLs? It seems like you could probably use a third-party URL template rendering library for this, something like:

const ConfirmEmail = "/confirm/{token}"

huma.Get(api, ConfirmEmail, userapi.ConfirmEmailHandler)

emailConfirmationLink := urltemplate.Render(ConfirmEmail, map[string]string{"token": user.EmailConfirmationToken})

Is there a reason you need this in the core Huma library instead? If you don't want an additional dependency you could write a quick/simple string replace implementation.

func Render(template string, params map[string]string) string {
  for k, v := range params {
    template = strings.ReplaceAll(template, "{" + k + "}", v)
  }
  return template
}

@bioform
Copy link
Author

bioform commented Dec 9, 2024

Thank you for the suggestion! The approach you outlined is valid and works well for simple use cases. However, I’m thinking of this feature more as syntactic sugar that could improve clarity and reduce boilerplate, especially when dealing with a larger set of routes.

For example, with the proposed approach:

const ConfirmEmail = "/confirm/{token}"
huma.Get(api, ConfirmEmail, userapi.ConfirmEmailHandler)

While functional, it may start to feel cluttered or disconnected as the number of routes grows. A typical setup might look like this:

routes := &Routes{
    ConfirmEmail:      "/confirm/{token}",
    SomeAnotherRoute:  "/another/{id}",
    // ...
}

huma.Get(api, routes.ConfirmEmail, userapi.ConfirmEmailHandler)
huma.Get(api, routes.SomeAnotherRoute, userapi.SomeAnotherHandler)
// ...

In such cases, the route paths are managed separately from their related handlers, which can make the code harder to read and navigate, particularly for larger APIs.

Embedding the ability to assign routes directly to variables as part of the Huma library would centralize route definitions and their usage. For example:

huma.Get(api, "/confirm/{token}", userapi.ConfirmEmailHandler).AssignTo(&routes.ConfirmEmail)

// Later usage
emailConfirmationLink := routes.ConfirmEmail.Url(baseUrl, user.EmailConfirmationToken)

This approach keeps routes and their handlers closely coupled, improving maintainability and making the codebase more intuitive. While it’s possible to implement similar functionality with external libraries or custom code, having this natively within the Huma library would provide a more cohesive and streamlined experience for developers.

@bioform
Copy link
Author

bioform commented Dec 13, 2024

BTW, to build an absolute route URL we need to know the server URL, like here:

var config = huma.DefaultConfig("My API", "1.0.0")

func init() {
	config.Components.SecuritySchemes = map[string]*huma.SecurityScheme{
		"bearer": {
			Type:         "http",
			Scheme:       "bearer",
			BearerFormat: "JWT",
		},
	}
	config.Servers = []*huma.Server{{URL: "/api"}}
}

Since the Huma already knows how to get this value - it can simplify things a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants