Skip to content

Commit

Permalink
Move middlewares into handlers package (#204)
Browse files Browse the repository at this point in the history
* Add NewEndpoints method

* Move middlewares to handlers package

* Move package handler to handlers

* Combine endpoint and service middlewares into one file
  • Loading branch information
adamryman committed Jul 25, 2017
1 parent 096ba69 commit 7594080
Show file tree
Hide file tree
Showing 24 changed files with 178 additions and 269 deletions.
9 changes: 3 additions & 6 deletions TUTORIAL.md
Expand Up @@ -79,10 +79,8 @@ In your terminal, go to the folder containing echo.proto and run `truss *.proto`
| ├── echo.pb.go
| ├── handlers
| │   ├── handlers.go
| │   └── hooks.go
| ├── middlewares
| │   ├── endpoints.go
| │   └── service.go
| │   ├── hooks.go
| │   └── middlewares.go
| └── svc
| └── ...
└── echo.proto
Expand All @@ -91,14 +89,13 @@ From the top down, within `echo-service/`:
- `docs/` contains the generated documentation of the service API
- `svc/` contains the wiring and encoding protocols necessary for service communication (generated code)
- `handlers/handlers.go` is populated with stubs where you will add the business logic
- `middlewares/` is where you can put the middlewares (NOP by default)
- `cmd/echo/` contains the client side CLI (useful for testing)
- `cmd/echo-server/` contains the service main, which you will build and run shortly
- `echo.pb.go` contains the RPC interface definitions and supporting structures that have been translated from `echo.proto` to golang

If you try to build and run your service now, it will respond with empty messages. There is no business logic yet! We shall add it in the next step.

You can safely modify only the files in handlers/ and middlewares/. Changes to any other files will be lost the next time you re-generate the service with truss.
You can safely modify only the files in handlers/. Changes to any other files will be lost the next time you re-generate the service with truss.

## Implement business logic

Expand Down
2 changes: 1 addition & 1 deletion USAGE.md
@@ -1,7 +1,7 @@
# Using truss
## Our Contract

1. Modify ONLY the files in `handlers/` and `middlewares/`.
1. Modify ONLY the files in `handlers/`.

User logic can be imported and executed within the functions in the handlers. It can also be added as _unexported_ helper functions in the handler file.

Expand Down
1 change: 0 additions & 1 deletion cmd/_integration-tests/middlewares/Makefile
Expand Up @@ -12,7 +12,6 @@ all: test
test:
@echo -e '$(TRUSS_MSG)'
truss middlewares-test.proto
cp -r middlewares middlewarestest-service
cp -r handlers middlewarestest-service
@echo -e '$(TEST_RUNNING_MSG)'
go test -v
Expand Down
@@ -1,9 +1,10 @@
package middlewares
package handlers

import (
"github.com/go-kit/kit/endpoint"
"golang.org/x/net/context"

pb "github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service"
svc "github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service/svc"
)

Expand All @@ -27,6 +28,10 @@ func WrapEndpoints(in svc.Endpoints) svc.Endpoints {
return in
}

func WrapService(in pb.MiddlewaresTestServer) pb.MiddlewaresTestServer {
return in
}

func addBoolToContext(key string) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
Expand Down
9 changes: 0 additions & 9 deletions cmd/_integration-tests/middlewares/middlewares/service.go

This file was deleted.

7 changes: 3 additions & 4 deletions cmd/_integration-tests/middlewares/setup_test.go
Expand Up @@ -5,8 +5,7 @@ import (
"testing"

pb "github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service"
handler "github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service/handlers"
"github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service/middlewares"
"github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service/handlers"
svc "github.com/TuneLab/truss/cmd/_integration-tests/middlewares/middlewarestest-service/svc"
)

Expand All @@ -16,7 +15,7 @@ func TestMain(m *testing.M) {

var service pb.MiddlewaresTestServer
{
service = handler.NewService()
service = handlers.NewService()
}

// Endpoint domain.
Expand All @@ -30,7 +29,7 @@ func TestMain(m *testing.M) {
LabeledTestHandlerEndpoint: labeledTestHandler,
}

middlewareEndpoints = middlewares.WrapEndpoints(middlewareEndpoints)
middlewareEndpoints = handlers.WrapEndpoints(middlewareEndpoints)

os.Exit(m.Run())
}
5 changes: 2 additions & 3 deletions cmd/_integration-tests/transport/http_benchmarks_test.go
Expand Up @@ -20,7 +20,6 @@ import (
httpclient "github.com/TuneLab/truss/cmd/_integration-tests/transport/transportpermutations-service/svc/client/http"

"github.com/TuneLab/truss/cmd/_integration-tests/transport/transportpermutations-service/handlers"
"github.com/TuneLab/truss/cmd/_integration-tests/transport/transportpermutations-service/middlewares"
"github.com/TuneLab/truss/cmd/_integration-tests/transport/transportpermutations-service/svc"

httptransport "github.com/go-kit/kit/transport/http"
Expand Down Expand Up @@ -64,8 +63,8 @@ func BenchmarkGetWithQueryClient_NoNetwork(b *testing.B) {
var service pb.TransportPermutationsServer
{
service = handlers.NewService()
// Wrap Service with middlewares. See middlewares/service.go
service = middlewares.WrapService(service)
// Wrap Service with middlewares. See handlers/service_middlewares.go
service = handlers.WrapService(service)
}
var getwithqueryEndpoint = svc.MakeGetWithQueryEndpoint(service)
endpoints := svc.Endpoints{
Expand Down
23 changes: 8 additions & 15 deletions gengokit/generator/gen.go
Expand Up @@ -12,8 +12,7 @@ import (
"github.com/pkg/errors"

"github.com/TuneLab/truss/gengokit"
"github.com/TuneLab/truss/gengokit/handler"
"github.com/TuneLab/truss/gengokit/middlewares"
"github.com/TuneLab/truss/gengokit/handlers"
templFiles "github.com/TuneLab/truss/gengokit/template"

"github.com/TuneLab/truss/svcdef"
Expand Down Expand Up @@ -60,29 +59,23 @@ func generateResponseFile(templFP string, data *gengokit.Data, prevFile io.Reade
actualFP := templatePathToActual(templFP, data.Service.Name)

switch templFP {
case handler.ServerHandlerPath:
h, err := handler.New(data.Service, prevFile)
case handlers.ServerHandlerPath:
h, err := handlers.New(data.Service, prevFile)
if err != nil {
return nil, errors.Wrapf(err, "cannot parse previous handler: %q", actualFP)
}

if genCode, err = h.Render(templFP, data); err != nil {
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
}
case handler.HookPath:
hook := handler.NewHook(prevFile)
case handlers.HookPath:
hook := handlers.NewHook(prevFile)
if genCode, err = hook.Render(templFP, data); err != nil {
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
}
case middlewares.EndpointsPath:
m := middlewares.New()
m.LoadEndpoints(prevFile)
if genCode, err = m.Render(templFP, data); err != nil {
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
}
case middlewares.ServicePath:
m := middlewares.New()
m.LoadService(prevFile)
case handlers.MiddlewaresPath:
m := handlers.NewMiddlewares()
m.Load(prevFile)
if genCode, err = m.Render(templFP, data); err != nil {
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
}
Expand Down
@@ -1,4 +1,4 @@
package handler
package handlers

import (
"go/ast"
Expand Down
9 changes: 5 additions & 4 deletions gengokit/handler/handler.go → gengokit/handlers/handlers.go
@@ -1,6 +1,6 @@
// Package handler manages the exported methods in the service handler code
// Package handlers manages the exported methods in the service handler code
// adding/removing exported methods to match the service definition.
package handler
package handlers

import (
"bytes"
Expand All @@ -15,6 +15,7 @@ import (
"github.com/pkg/errors"

"github.com/TuneLab/truss/gengokit"
"github.com/TuneLab/truss/gengokit/handlers/templates"
"github.com/TuneLab/truss/svcdef"
)

Expand Down Expand Up @@ -286,9 +287,9 @@ func exprString(e ast.Expr) string {

func applyServerTempl(exec *gengokit.Data) (io.Reader, error) {
log.Debug("Rendering handler for the first time")
return exec.ApplyTemplate(serverTempl, "ServerTempl")
return exec.ApplyTemplate(templates.Handlers, "ServerTempl")
}

func applyServerMethsTempl(exec handlerData) (io.Reader, error) {
return gengokit.ApplyTemplate(serverMethsTempl, "ServerMethsTempl", exec, gengokit.FuncMap)
return gengokit.ApplyTemplate(templates.HandlerMethods, "ServerMethsTempl", exec, gengokit.FuncMap)
}
5 changes: 3 additions & 2 deletions gengokit/handler/hooks.go → gengokit/handlers/hooks.go
@@ -1,10 +1,11 @@
package handler
package handlers

import (
"io"
"strings"

"github.com/TuneLab/truss/gengokit"
"github.com/TuneLab/truss/gengokit/handlers/templates"
)

const HookPath = "handlers/hooks.gotemplate"
Expand All @@ -24,7 +25,7 @@ type HookRender struct {
// a brand new copy from the template.
func (h *HookRender) Render(_ string, _ *gengokit.Data) (io.Reader, error) {
if h.prev == nil {
return strings.NewReader(hookTempl), nil
return strings.NewReader(templates.Hook), nil
} else {
return h.prev, nil
}
Expand Down
44 changes: 44 additions & 0 deletions gengokit/handlers/middlewares.go
@@ -0,0 +1,44 @@
package handlers

import (
"io"

"github.com/pkg/errors"

"github.com/TuneLab/truss/gengokit"
"github.com/TuneLab/truss/gengokit/handlers/templates"
)

// MiddlewaresPath is the path to the middleware gotemplate file.
const MiddlewaresPath = "handlers/middlewares.gotemplate"

// NewMiddleware returns a Renderable that renders the middlewares.go file.
func NewMiddlewares() *Middlewares {
var m Middlewares

return &m
}

// Middlewares satisfies the gengokit.Renderable interface to render
// middlewares.
type Middlewares struct {
prev io.Reader
}

// Load loads the previous version of the middleware file.
func (m *Middlewares) Load(prev io.Reader) {
m.prev = prev
}

// Render creates the middlewares.go file. With no previous version it renders
// the templates, if there was a previous version loaded in, it passes that
// through.
func (m *Middlewares) Render(path string, data *gengokit.Data) (io.Reader, error) {
if path != MiddlewaresPath {
return nil, errors.Errorf("cannot render unknown file: %q", path)
}
if m.prev != nil {
return m.prev, nil
}
return data.ApplyTemplate(templates.Middlewares, "Middlewares")
}
@@ -1,4 +1,4 @@
package middlewares
package handlers

import (
"io/ioutil"
Expand All @@ -12,88 +12,10 @@ import (
"github.com/TuneLab/truss/svcdef"
)

var gopath []string

func init() {
gopath = filepath.SplitList(os.Getenv("GOPATH"))
}

func TestNewServiceMiddleware(t *testing.T) {
var wantService = `
package middlewares
import (
pb "github.com/TuneLab/truss/gengokit/general-service"
)
func WrapService(in pb.ProtoServiceServer) pb.ProtoServiceServer {
return in
}
`

_, data, err := generalService()
if err != nil {
t.Fatal(err)
}

middleware := New()
service, err := middleware.Render(ServicePath, data)
if err != nil {
t.Fatal(err)
}

serviceBytes, err := ioutil.ReadAll(service)
if err != nil {
t.Fatal(err)
}

wantFormatted, serviceFormatted, diff := thelper.DiffGoCode(wantService, string(serviceBytes))
if wantFormatted != serviceFormatted {
t.Fatalf("Serivce middleware different than expected:\n\n%s", diff)
}
}

func TestRenderPrevService(t *testing.T) {
var wantService = `
package middlewares
import (
pb "github.com/TuneLab/truss/gengokit/general-service"
)
func WrapService(in pb.ProtoServiceServer) pb.ProtoServiceServer {
return in
}
func FooBar() error {
return nil
}
`
_, data, err := generalService()
if err != nil {
t.Fatal(err)
}

middleware := New()

middleware.LoadService(strings.NewReader(wantService))

service, err := middleware.Render(ServicePath, data)
if err != nil {
t.Fatal(err)
}

serviceBytes, err := ioutil.ReadAll(service)
if err != nil {
t.Fatal(err)
}

wantFormatted, serviceFormatted, diff := thelper.DiffGoCode(wantService, string(serviceBytes))
if wantFormatted != serviceFormatted {
t.Fatalf("Sevice middleware modified unexpectedly:\n\n%s", diff)
}
}

func TestRenderPrevEndpoints(t *testing.T) {
var wantEndpoints = `
package middlewares
Expand Down Expand Up @@ -130,11 +52,11 @@ func TestRenderPrevEndpoints(t *testing.T) {
t.Fatal(err)
}

middleware := New()
middleware := NewMiddlewares()

middleware.LoadEndpoints(strings.NewReader(wantEndpoints))
middleware.Load(strings.NewReader(wantEndpoints))

endpoints, err := middleware.Render(EndpointsPath, data)
endpoints, err := middleware.Render(MiddlewaresPath, data)
if err != nil {
t.Fatal(err)
}
Expand All @@ -156,7 +78,7 @@ func TestRenderUnknownFile(t *testing.T) {
t.Fatal(err)
}

middleware := New()
middleware := NewMiddlewares()

_, err = middleware.Render("not/valid/file.go", data)
if err == nil {
Expand Down

0 comments on commit 7594080

Please sign in to comment.