From e5f6bce86fe7ad61939986c538d7a70b63236b82 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sun, 5 Aug 2018 13:51:05 +0300 Subject: [PATCH] examples: writing an API for the Apache Kafka: add a root handler for routes documentation to make navigation easier and add some other methods that may find them useful for request state and routes description Former-commit-id: 3775aab2386051b23e127ccc9e3a6accdfdee6d0 --- _examples/http_responsewriter/sse/main.go | 2 +- .../tutorial/api-for-apache-kafka/0_docs.png | Bin 0 -> 29953 bytes .../tutorial/api-for-apache-kafka/README.md | 2 + .../tutorial/api-for-apache-kafka/src/main.go | 48 ++++++++++++++++++ context/application.go | 5 ++ context/route.go | 13 +++++ core/router/api_builder.go | 19 +++++++ core/router/route.go | 10 +++- 8 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 _examples/tutorial/api-for-apache-kafka/0_docs.png 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 0000000000000000000000000000000000000000..2c81a744de08ae097b2d3021e52e9f733f9719a1 GIT binary patch literal 29953 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 VaNVr>)4y{}locTgMRIQf{|7dqf589% literal 0 HcmV?d00001 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 +}