diff --git a/_examples/http_responsewriter/sse/main.go b/_examples/http_responsewriter/sse/main.go index 5d0fe05d..b537524b 100644 --- a/_examples/http_responsewriter/sse/main.go +++ b/_examples/http_responsewriter/sse/main.go @@ -114,7 +114,7 @@ func (b *Broker) ServeHTTP(ctx context.Context) { ctx.Writef("data: %s\n\n", <-messageChan) // or json: data:{obj}. - // Flush the data immediatly instead of buffering it for later. + // Flush the data immediately instead of buffering it for later. flusher.Flush() } } diff --git a/_examples/tutorial/api-for-apache-kafka/0_docs.png b/_examples/tutorial/api-for-apache-kafka/0_docs.png new file mode 100644 index 00000000..2c81a744 Binary files /dev/null and b/_examples/tutorial/api-for-apache-kafka/0_docs.png differ diff --git a/_examples/tutorial/api-for-apache-kafka/README.md b/_examples/tutorial/api-for-apache-kafka/README.md index b478b229..bb53e1d0 100644 --- a/_examples/tutorial/api-for-apache-kafka/README.md +++ b/_examples/tutorial/api-for-apache-kafka/README.md @@ -9,6 +9,8 @@ Read [the fully functional example](src/main.go). ## Screens +![](0_docs.png) + ![](1_create_topic.png) ![](2_list_topics.png) diff --git a/_examples/tutorial/api-for-apache-kafka/src/main.go b/_examples/tutorial/api-for-apache-kafka/src/main.go index 4448a349..9b7b5d05 100644 --- a/_examples/tutorial/api-for-apache-kafka/src/main.go +++ b/_examples/tutorial/api-for-apache-kafka/src/main.go @@ -65,12 +65,60 @@ func main() { } } + app.Get("/", docsHandler) + + // GET : http://localhost:8080 // POST, GET: http://localhost:8080/api/v1/topics // POST : http://localhost:8080/apiv1/topics/{topic}/produce?key=my-key // GET : http://localhost:8080/apiv1/topics/{topic}/consume?partition=0&offset=0 (these url query parameters are optional) app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) } +// simple use-case, you can use templates and views obviously, see the "_examples/views" examples. +func docsHandler(ctx iris.Context) { + ctx.ContentType("text/html") // or ctx.HTML(fmt.Sprintf(...)) + ctx.Writef(` + + + + `) + defer ctx.Writef("") + + ctx.Writef("") + defer ctx.Writef("") + + ctx.Writef(` + + + + + + + `) + defer ctx.Writef(`
MethodPathHandler
`) + + registeredRoutes := ctx.Application().GetRoutesReadOnly() + for _, r := range registeredRoutes { + if r.Path() == "/" { // don't list the root, current one. + continue + } + + ctx.Writef(` + + %s + %s%s + %s + + `, r.Method(), ctx.Host(), r.Path(), r.MainHandlerName()) + } +} + type httpError struct { Code int `json:"code"` Reason string `json:"reason"` diff --git a/context/application.go b/context/application.go index 9a94fbcb..36c973a0 100644 --- a/context/application.go +++ b/context/application.go @@ -42,6 +42,11 @@ type Application interface { // Look core/router/APIBuilder#GetRoute for more. GetRouteReadOnly(routeName string) RouteReadOnly + // GetRoutesReadOnly returns the registered "read-only" routes. + // + // Look core/router/APIBuilder#GetRoutes for more. + GetRoutesReadOnly() []RouteReadOnly + // FireErrorCode executes an error http status code handler // based on the context's status code. // diff --git a/context/route.go b/context/route.go index 52f29515..e632f11f 100644 --- a/context/route.go +++ b/context/route.go @@ -1,5 +1,7 @@ package context +import "github.com/kataras/iris/core/router/macro" + // RouteReadOnly allows decoupled access to the current route // inside the context. type RouteReadOnly interface { @@ -29,4 +31,15 @@ type RouteReadOnly interface { // ResolvePath returns the formatted path's %v replaced with the args. ResolvePath(args ...string) string + + // Tmpl returns the path template, + // it contains the parsed template + // for the route's path. + // May contain zero named parameters. + // + // Available after the build state, i.e a request handler or Iris Configurator. + Tmpl() macro.Template + + // MainHandlerName returns the first registered handler for the route. + MainHandlerName() string } diff --git a/core/router/api_builder.go b/core/router/api_builder.go index 977f5d04..242fbadb 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -437,6 +437,7 @@ func (api *APIBuilder) GetRoute(routeName string) *Route { // One note: "routeName" should be case-sensitive. Used by the context to get the current route. // It returns an interface instead to reduce wrong usage and to keep the decoupled design between // the context and the routes. +// Look `GetRoutesReadOnly` to fetch a list of all registered routes. // // Look `GetRoute` for more. func (api *APIBuilder) GetRouteReadOnly(routeName string) context.RouteReadOnly { @@ -447,6 +448,24 @@ func (api *APIBuilder) GetRouteReadOnly(routeName string) context.RouteReadOnly return routeReadOnlyWrapper{r} } +// GetRoutesReadOnly returns the registered routes with "read-only" access, +// you cannot and you should not change any of these routes' properties on request state, +// you can use the `GetRoutes()` for that instead. +// +// It returns interface-based slice instead of the real ones in order to apply +// safe fetch between context(request-state) and the builded application. +// +// Look `GetRouteReadOnly` too. +func (api *APIBuilder) GetRoutesReadOnly() []context.RouteReadOnly { + routes := api.GetRoutes() + readOnlyRoutes := make([]context.RouteReadOnly, len(routes)) + for i, r := range routes { + readOnlyRoutes[i] = routeReadOnlyWrapper{r} + } + + return readOnlyRoutes +} + // Use appends Handler(s) to the current Party's routes and child routes. // If the current Party is the root, then it registers the middleware to all child Parties' routes too. // diff --git a/core/router/route.go b/core/router/route.go index 205687c1..346c068d 100644 --- a/core/router/route.go +++ b/core/router/route.go @@ -114,7 +114,7 @@ func (r Route) String() string { r.Method, r.Subdomain, r.Tmpl().Src) } -// Tmpl returns the path template, i +// Tmpl returns the path template, // it contains the parsed template // for the route's path. // May contain zero named parameters. @@ -249,3 +249,11 @@ func (rd routeReadOnlyWrapper) Path() string { func (rd routeReadOnlyWrapper) Trace() string { return rd.Route.Trace() } + +func (rd routeReadOnlyWrapper) Tmpl() macro.Template { + return rd.Route.Tmpl() +} + +func (rd routeReadOnlyWrapper) MainHandlerName() string { + return rd.Route.MainHandlerName +}