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

Route groups break docs #684

Open
bilus opened this issue Dec 18, 2024 · 2 comments
Open

Route groups break docs #684

bilus opened this issue Dec 18, 2024 · 2 comments
Labels
question Further information is requested

Comments

@bilus
Copy link

bilus commented Dec 18, 2024

I followed the docs about Route Groups & Base URLs to group my API under /v1/sports. I'm using Chi and identical structure to the example.

The relevant part of my code:

	app := NewApp(client)
	api := API{app: app}

	// Create a new router & API.
	router := chi.NewMux()
	router.Route("/v1/sports", func(router chi.Router) {
		config := huma.DefaultConfig("My API", "1.0.0")
		config.CreateHooks = nil // Do not add $schema links.
		// config.OpenAPIPath = "/v1/sports/openapi"

		routes := humachi.New(router, config)
		// My routes.
	})
	chi.Walk(router, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
		fmt.Printf("[%s]: '%s'\n", method, route)
		return nil
	})

It generates these routes:

...
[GET]: '/v1/sports/docs'
[GET]: '/v1/sports/openapi-3.0.json'
[GET]: '/v1/sports/openapi-3.0.yaml'
[GET]: '/v1/sports/openapi.json'
[GET]: '/v1/sports/openapi.yaml'

The problem is the docs HTML at /v1/sports/docs accesses the openapi.yaml using the following path: /openapi.yaml producing:

image

Setting OpenAPIPath doesn't help. If I uncomment the following line:

		config.OpenAPIPath = "/v1/sports/openapi"

...this is the routes it generates:

...
[GET]: '/v1/sports/docs'
[GET]: '/v1/sports/v1/sports/openapi-3.0.json'
[GET]: '/v1/sports/v1/sports/openapi-3.0.yaml'
[GET]: '/v1/sports/v1/sports/openapi.json'
[GET]: '/v1/sports/v1/sports/openapi.yaml'

So now, when I'm accessing /v1/sports/docs, the error becomes:

image

It's because it expects the "correct" path based on the following code in api.go:

    <elements-api
      apiDescriptionUrl="` + openAPIPath + `.yaml"
      router="hash"
  apiDescriptionUrl="` + openAPIPath + `.yaml"
@danielgtaylor danielgtaylor added the question Further information is requested label Dec 19, 2024
@danielgtaylor
Copy link
Owner

@bilus yes I don't think this is supported at the moment. You can get around it by providing your own docs route, for example setting config.DocsPath = "" and then doing something like:

router.Get("/docs", func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	w.Write([]byte(`<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="referrer" content="same-origin" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Sports API Docs</title>
<!-- Embed elements Elements via Web Component -->
<link href="https://unpkg.com/@stoplight/[email protected]/styles.min.css" rel="stylesheet" />
<script src="https://unpkg.com/@stoplight/[email protected]/web-components.min.js"
				integrity="sha256-985sDMZYbGa0LDS8jYmC4VbkVlh7DZ0TWejFv+raZII="
				crossorigin="anonymous"></script>
</head>
<body style="height: 100vh;">

<elements-api
	apiDescriptionUrl="/v1/sports/openapi.yaml"
	router="hash"
	layout="sidebar"
	tryItCredentialsPolicy="same-origin"
/>

</body>
</html>`))
})

This is copied from https://github.com/danielgtaylor/huma/blob/main/api.go#L451-L489

@jamesleeht
Copy link

jamesleeht commented Dec 21, 2024

Hi @danielgtaylor thanks for the great library. What is the recommended way to setup the route groups without breaking docs for humachi? I realized humafiber has a NewWithGroup method, but that doesn't seem to exist for humachi.

I'm doing something where I use the same Huma config for the whole API, but have separate structs which take in a prefix variable and append it to the path when registering to Huma.

	baseRouter.Route("/api", func(r chi.Router) {
		humaCfg := huma.DefaultConfig("Something API", "1.0.0")
		humaCfg.Servers = []*huma.Server{
			{
				URL:         "https://something.com",
				Description: "Production server",
			},
		}

		api := humachi.New(r, humaCfg)
		authClient := auth.NewAuthClient(config)
		authMiddleware := auth.GetAuthMiddleware(api, authClient)

		// Users
		userRouter := usersRg.NewRouteGroup(userService)
		userRouter.RegisterRouter("/users", api, authMiddleware)
	})
func (rg *RouteGroup) RegisterRouter(basePath string, api huma.API, authMiddleware common.Middleware) {
	huma.Register(api, huma.Operation{
		OperationID: "getUserProfileByUsername",
		Method:      http.MethodGet,
		Path:        basePath + "/{username}",
		Security:    auth.SecurityScheme,
	}, rg.GetUserProfileByUsername)

	huma.Register(api, huma.Operation{
		OperationID: "updateUsername",
		Method:      http.MethodPut,
		Path:        basePath + "/current/username",
		Security:    auth.SecurityScheme,
		Middlewares: huma.Middlewares{authMiddleware},
	}, rg.UpdateUsername)
}

@festo festo mentioned this issue Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants