Skip to content

Commit 0f410ab

Browse files
authored
add support for prefixing routes (#23)
* honour basePath from the API spec that can be overriden when constructing the server
1 parent ebff674 commit 0f410ab

File tree

10 files changed

+149
-21
lines changed

10 files changed

+149
-21
lines changed

example/framework.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,10 @@ func (v *Validator) ValidateRequest(request interface{}) (*ValidationErrorsObjec
582582
}
583583

584584
var (
585-
GitCommit string = "8bf73b60aa3f094512524ebd8d5fe96318cbed59"
586-
GitBranch string = "feature-query-default-values"
585+
GitCommit string = "a8719e7d76227cf28d355fef25f8f275e6d51621"
586+
GitBranch string = "master"
587587
GitTag string = "v1.0.0"
588-
BuildTime string = "Mo 13. Sep 14:55:38 CEST 2021"
588+
BuildTime string = "Wed 27 Oct 2021 22:16:50 BST"
589589
)
590590

591591
type VersionInfo struct {
@@ -968,6 +968,7 @@ type (
968968
ErrorHandler ErrorHandler
969969
Middleware []Middleware
970970
OnStart func(router *routing.Router)
971+
Prefix string
971972
}
972973

973974
Middleware struct {
@@ -991,6 +992,7 @@ type (
991992
after []routing.Handler
992993
before []routing.Handler
993994
SwaggerSpec string
995+
Prefix string
994996
}
995997
)
996998

@@ -1010,12 +1012,17 @@ func newServer(opts *ServerOpts) *Server {
10101012

10111013
server := &Server{
10121014
ErrorLogger: opts.ErrorHandler,
1015+
Prefix: "",
10131016
}
10141017

10151018
if opts.OnStart != nil {
10161019
server.OnStart = opts.OnStart
10171020
}
10181021

1022+
if opts.Prefix != "" {
1023+
server.Prefix = opts.Prefix
1024+
}
1025+
10191026
if len(opts.Middleware) != 0 {
10201027
before := make([]routing.Handler, 0)
10211028
after := make([]routing.Handler, 0)
@@ -1055,14 +1062,23 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
10551062
if server.before != nil {
10561063
beforeStack = append(beforeStack, server.before...)
10571064
}
1058-
router.Use(beforeStack...)
1065+
1066+
prefix := server.Prefix
1067+
1068+
if prefix == "/" {
1069+
prefix = ""
1070+
}
1071+
1072+
rg := router.Group(prefix)
1073+
1074+
rg.Use(beforeStack...)
10591075

10601076
var afterStack []routing.Handler
10611077
if server.after != nil {
10621078
afterStack = append(afterStack, server.after...)
10631079
}
10641080

1065-
router.Get("/spec", func(c *routing.Context) error {
1081+
rg.Get("/spec", func(c *routing.Context) error {
10661082
return c.Write(server.SwaggerSpec)
10671083
})
10681084

@@ -1086,7 +1102,7 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
10861102
handler = append(handler, after...)
10871103
handler = append(handler, afterStack...)
10881104

1089-
router.To(route.Method, route.Path, handler...)
1105+
rg.To(route.Method, route.Path, handler...)
10901106
}
10911107

10921108
return router, nil

example/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import (
88
)
99

1010
func NewTodoServiceServer(options *ServerOpts) *TodoServiceServer {
11+
if options == nil {
12+
options = &ServerOpts{}
13+
}
14+
if options.Prefix == "" {
15+
options.Prefix = ""
16+
}
17+
1118
serverWrapper := &TodoServiceServer{Server: newServer(options), Validator: NewValidation()}
1219
serverWrapper.Server.SwaggerSpec = swagger
1320
serverWrapper.registerValidators()

framework/framework_code.go

Lines changed: 3 additions & 2 deletions
Large diffs are not rendered by default.

framework/framework_code_client.go

Lines changed: 3 additions & 2 deletions
Large diffs are not rendered by default.

framework/framework_code_server.go

Lines changed: 3 additions & 2 deletions
Large diffs are not rendered by default.

generator/server_generator.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ func (gen *goServerGenerator) Generate(path, pckg string, validators ValidatorMa
7777
stmts.Line()
7878
}
7979

80+
basePath := gen.Spec.Spec.BasePath
81+
82+
if basePath == "/" {
83+
basePath = ""
84+
}
85+
86+
stmts.If(jen.Id("options").Op("==").Nil()).Block(
87+
jen.Id("options").Op("=").Op("&").Id("ServerOpts").Block(),
88+
)
89+
90+
stmts.If(jen.Id("options").Dot("Prefix").Op("==").Lit("")).Block(jen.Id("options").Dot("Prefix").Op("=").Lit(basePath)).Line()
91+
8092
wrapperArgs := []jen.Code{
8193
jen.Id("Server").Op(":").Id("newServer").Call(jen.Id("options")),
8294
jen.Id("Validator").Op(":").Id("NewValidation").Call(),

internal/framework/xserver/server.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type (
3030
ErrorHandler ErrorHandler
3131
Middleware []Middleware
3232
OnStart func(router *routing.Router)
33+
Prefix string
3334
}
3435

3536
Middleware struct {
@@ -53,6 +54,7 @@ type (
5354
after []routing.Handler
5455
before []routing.Handler
5556
SwaggerSpec string
57+
Prefix string
5658
}
5759
)
5860

@@ -75,12 +77,17 @@ func NewServer(opts *ServerOpts) *Server {
7577

7678
server := &Server{
7779
ErrorLogger: opts.ErrorHandler,
80+
Prefix: "",
7881
}
7982

8083
if opts.OnStart != nil {
8184
server.OnStart = opts.OnStart
8285
}
8386

87+
if opts.Prefix != "" {
88+
server.Prefix = opts.Prefix
89+
}
90+
8491
if len(opts.Middleware) != 0 {
8592
before := make([]routing.Handler, 0)
8693
after := make([]routing.Handler, 0)
@@ -120,14 +127,23 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
120127
if server.before != nil {
121128
beforeStack = append(beforeStack, server.before...)
122129
}
123-
router.Use(beforeStack...)
130+
131+
prefix := server.Prefix
132+
133+
if prefix == "/" {
134+
prefix = ""
135+
}
136+
137+
rg := router.Group(prefix)
138+
139+
rg.Use(beforeStack...)
124140

125141
var afterStack []routing.Handler
126142
if server.after != nil {
127143
afterStack = append(afterStack, server.after...)
128144
}
129145

130-
router.Get("/spec", func(c *routing.Context) error {
146+
rg.Get("/spec", func(c *routing.Context) error {
131147
return c.Write(server.SwaggerSpec)
132148
})
133149

@@ -151,7 +167,7 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
151167
handler = append(handler, after...)
152168
handler = append(handler, afterStack...)
153169

154-
router.To(route.Method, route.Path, handler...)
170+
rg.To(route.Method, route.Path, handler...)
155171
}
156172

157173
return router, nil

tests/api/framework.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,10 @@ func (v *Validator) ValidateRequest(request interface{}) (*ValidationErrorsObjec
582582
}
583583

584584
var (
585-
GitCommit string = "8bf73b60aa3f094512524ebd8d5fe96318cbed59"
586-
GitBranch string = "feature-query-default-values"
585+
GitCommit string = "a8719e7d76227cf28d355fef25f8f275e6d51621"
586+
GitBranch string = "master"
587587
GitTag string = "v1.0.0"
588-
BuildTime string = "Mo 13. Sep 14:55:38 CEST 2021"
588+
BuildTime string = "Wed 27 Oct 2021 22:16:50 BST"
589589
)
590590

591591
type VersionInfo struct {
@@ -968,6 +968,7 @@ type (
968968
ErrorHandler ErrorHandler
969969
Middleware []Middleware
970970
OnStart func(router *routing.Router)
971+
Prefix string
971972
}
972973

973974
Middleware struct {
@@ -991,6 +992,7 @@ type (
991992
after []routing.Handler
992993
before []routing.Handler
993994
SwaggerSpec string
995+
Prefix string
994996
}
995997
)
996998

@@ -1010,12 +1012,17 @@ func newServer(opts *ServerOpts) *Server {
10101012

10111013
server := &Server{
10121014
ErrorLogger: opts.ErrorHandler,
1015+
Prefix: "",
10131016
}
10141017

10151018
if opts.OnStart != nil {
10161019
server.OnStart = opts.OnStart
10171020
}
10181021

1022+
if opts.Prefix != "" {
1023+
server.Prefix = opts.Prefix
1024+
}
1025+
10191026
if len(opts.Middleware) != 0 {
10201027
before := make([]routing.Handler, 0)
10211028
after := make([]routing.Handler, 0)
@@ -1055,14 +1062,23 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
10551062
if server.before != nil {
10561063
beforeStack = append(beforeStack, server.before...)
10571064
}
1058-
router.Use(beforeStack...)
1065+
1066+
prefix := server.Prefix
1067+
1068+
if prefix == "/" {
1069+
prefix = ""
1070+
}
1071+
1072+
rg := router.Group(prefix)
1073+
1074+
rg.Use(beforeStack...)
10591075

10601076
var afterStack []routing.Handler
10611077
if server.after != nil {
10621078
afterStack = append(afterStack, server.after...)
10631079
}
10641080

1065-
router.Get("/spec", func(c *routing.Context) error {
1081+
rg.Get("/spec", func(c *routing.Context) error {
10661082
return c.Write(server.SwaggerSpec)
10671083
})
10681084

@@ -1086,7 +1102,7 @@ func (server *Server) makeRouter(routes []RouteDescription) (*routing.Router, er
10861102
handler = append(handler, after...)
10871103
handler = append(handler, afterStack...)
10881104

1089-
router.To(route.Method, route.Path, handler...)
1105+
rg.To(route.Method, route.Path, handler...)
10901106
}
10911107

10921108
return router, nil

tests/api/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import (
1313
)
1414

1515
func NewVisAdminServer(options *ServerOpts) *VisAdminServer {
16+
if options == nil {
17+
options = &ServerOpts{}
18+
}
19+
if options.Prefix == "" {
20+
options.Prefix = ""
21+
}
22+
1623
serverWrapper := &VisAdminServer{Server: newServer(options), Validator: NewValidation()}
1724
serverWrapper.Server.SwaggerSpec = swagger
1825
serverWrapper.registerValidators()

tests/custom_prefix_api_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package tests
2+
3+
import (
4+
"log"
5+
"net/http"
6+
"testing"
7+
"time"
8+
9+
"github.com/ExperienceOne/apikit/tests/api"
10+
)
11+
12+
// Tests setting a custom prefix for api routes using ServerOpts.
13+
func TestCustomPrefix(t *testing.T) {
14+
middlewares := []api.Middleware{
15+
{Handler: api.RouterPanicMiddleware()},
16+
{Handler: api.RouterPopulateContextMiddleware()},
17+
}
18+
19+
testServerWrapper = api.NewVisAdminServer(&api.ServerOpts{
20+
Middleware: middlewares,
21+
ErrorHandler: log.Println,
22+
Prefix: "/my-custom-prefix",
23+
})
24+
25+
testServerWrapper.SetGetUsersHandler(api.GetUsers)
26+
27+
go testServerWrapper.Start(4568)
28+
29+
defer testServerWrapper.Server.Stop()
30+
31+
time.Sleep(1 * time.Second)
32+
33+
opts := api.Opts{
34+
Hooks: api.DevHook(),
35+
Ctx: nil,
36+
}
37+
38+
client := api.NewVisAdminClient(new(http.Client), "http://localhost:4568/my-custom-prefix", opts)
39+
40+
response, err := client.GetUsers(&api.GetUsersRequest{
41+
XAuth: "sessionID",
42+
})
43+
44+
if err != nil {
45+
t.Fatalf("error GetUsers failed: %v", err)
46+
}
47+
48+
if _, ok := response.(*api.GetUsers200Response); !ok {
49+
t.Fatalf("error GetUsers response is bad: %#v", err)
50+
}
51+
}

0 commit comments

Comments
 (0)