Permalink
Browse files

feat: http server

  • Loading branch information...
moul committed Nov 15, 2018
1 parent 56f785f commit 6fd644a1ecc161cdc610b2bdef30cd9628330351
Showing with 319 additions and 45 deletions.
  1. +16 −5 Makefile
  2. +41 −0 README.md
  3. +4 −3 build/docker/protoc/Dockerfile
  4. +4 −0 go.mod
  5. +6 −0 go.sum
  6. +2 −1 server/cobra.go
  7. +67 −5 server/server.go
  8. +68 −30 server/server.pb.go
  9. +107 −0 server/server.pb.gw.go
  10. +4 −1 server/server.proto
@@ -11,11 +11,13 @@ rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subs
GOPATH ?= $(HOME)/go
BIN = $(GOPATH)/bin/pathwar.pw
SOURCES = $(call rwildcard, ./, *.go)
OUR_SOURCES = $(filter-out $(call rwildcard,vendor//,*.go),$(SOURCES))
PROTOS = $(call rwildcard, ./, *.proto)
OUR_PROTOS = $(filter-out $(call rwildcard,vendor//,*.proto),$(PROTOS))
GENERATED_FILES = \
$(patsubst %.proto,%.pb.go,$(PROTOS)) \
$(call rwildcard ./, *.gen.go)
PROTOC_OPTS = -I/protobuf:.
PROTOC_OPTS = -I/protobuf:vendor:.
RUN_OPTS ?=

##
@@ -36,7 +38,7 @@ run: $(BIN)

.PHONY: install
install: $(BIN)
$(BIN): .generated $(SOURCES)
$(BIN): .generated $(OUR_SOURCES)
go install -v

.PHONY: clean
@@ -45,20 +47,29 @@ clean:

.PHONY: generate
generate: .generated
.generated: $(PROTOS)
.generated: $(OUR_PROTOS)
rm -f $(GENERATED_FILES)
go mod vendor
docker run \
--user="$(shell id -u)" \
--volume="$(PWD):/go/src/pathwar.pw" \
--workdir="/go/src/pathwar.pw" \
--entrypoint="sh" \
--rm \
moul/protoc-gen-gotemplate \
pathwar/protoc:v1 \
-xec "make _generate"
touch $@

.PHONY: _generate
_generate: $(GENERATED_FILES)

.PHONY: test
test: .generated
go test -v ./...

%.pb.go: %.proto
protoc $(PROTOC_OPTS) --gofast_out=plugins=grpc:"$(GOPATH)/src" "$(dir $<)"/*.proto
protoc \
$(PROTOC_OPTS) \
--grpc-gateway_out=logtostderr=true:"$(GOPATH)/src" \
--gofast_out=plugins=grpc:"$(GOPATH)/src" \
"$(dir $<)"/*.proto
@@ -1,2 +1,43 @@
# pathwar
Pathwar monorepo

## Production architecture (expected)

```
┌─────────────────────────────────────┐
│ pathwar server cluster │
│ │
│ ┌─────────────────────────────────┐ │
│ │┌─────────────┐ │ │
│ ││ │ │ │
│ ││ ssh proxy │ │ │
│ ││ │ │ │
│ │└─────────────┘ │ │
│ │┌─────────────┐ │ │
│ ││ │ │ │
│ ││ web │ │ │
│ ││ │ │ │
│ │└─────────────┘ pathwar server│ │
│ │┌─────────────┐ │ │
┌───────────┐ │ ││ │ │ │ ┌─────────┐
┌───────────┐ │ │ │ ││ http proxy │ │ │ │ │
│ │ │ │ │ ││ │ │ │ │ SQL │
│ users │──▶│ haproxy │──▶│ │└─────────────┘ │ │──▶│ cluster │
│ │ │ │ │ │┌─────────────┐ │ │ │ │
└───────────┘ │ │ │ ││ │ │ │ └─────────┘
└───────────┘ │ ││ api │ │ │
│ ││ │ │ │
│ │└─────────────┘ │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ │ │
│ │ pathwar server│ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ │ │
│ │ ...│ │
│ │ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────┘
```
@@ -3,12 +3,13 @@ FROM moul/protoc-gen-gotemplate:latest as pgg
FROM golang:1.11-alpine as builder
RUN apk --no-cache add make git go rsync libc-dev openssh docker
RUN go get -u -v \
github.com/opsee/protobuf/protoc-gen-gogoopsee
github.com/gogo/protobuf/protoc-gen-gofast \
github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway

FROM golang:1.11-alpine
RUN apk --no-cache add git make protobuf gcc libc-dev && \
mkdir -p /.cache/go-build && \
chmod -R 777 /.cache
mkdir -p /.cache/go-build && \
chmod -R 777 /.cache
COPY --from=pgg /go/bin/* /go/bin/
COPY --from=builder /go/bin/* /go/bin/
COPY --from=pgg /protobuf /protobuf
4 go.mod
@@ -2,6 +2,9 @@ module pathwar.pw

require (
github.com/golang/protobuf v1.2.0
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0
github.com/grpc-ecosystem/grpc-gateway v1.5.1
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/pkg/errors v0.8.0
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3
@@ -10,5 +13,6 @@ require (
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.9.1
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
google.golang.org/grpc v1.16.0
)
6 go.sum
@@ -8,8 +8,14 @@ github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200j
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:BWIsLfhgKhV5g/oF34aRjniBHLTZe5DNekSjbAjIS6c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/IwvnDIZ0LHJK1nk=
github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -7,7 +7,8 @@ import (
)

func serverSetupFlags(flags *pflag.FlagSet, opts *serverOptions) {
flags.StringVar(&opts.GRPCBind, "grpc-bind", ":4444", "grpc server address")
flags.StringVar(&opts.GRPCBind, "grpc-bind", ":9111", "gRPC server address")
flags.StringVar(&opts.HTTPBind, "http-bind", ":8000", "HTTP server address")
viper.BindPFlags(flags)
}

@@ -1,16 +1,26 @@
package server

import (
"context"
"encoding/json"
"net"
"net/http"

grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/pkg/errors"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

type serverOptions struct {
GRPCBind string
GRPCBind string
HTTPBind string
WithReflection bool
}

func (opts serverOptions) String() string {
@@ -19,15 +29,67 @@ func (opts serverOptions) String() string {
}

func server(opts *serverOptions) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

errs := make(chan error)
go func() { errs <- errors.Wrap(startGRPCServer(ctx, opts), "gRPC server error") }()
go func() { errs <- errors.Wrap(startHTTPServer(ctx, opts), "HTTP server error") }()
return <-errs
}

func startHTTPServer(ctx context.Context, opts *serverOptions) error {
mux := runtime.NewServeMux()
grpcOpts := []grpc.DialOption{grpc.WithInsecure()}
if err := RegisterServerHandlerFromEndpoint(ctx, mux, opts.GRPCBind, grpcOpts); err != nil {
return err
}
zap.L().Info("starting HTTP server", zap.String("bind", opts.HTTPBind))
return http.ListenAndServe(opts.HTTPBind, mux)
}

func startGRPCServer(ctx context.Context, opts *serverOptions) error {
listener, err := net.Listen("tcp", opts.GRPCBind)
if err != nil {
return errors.Wrap(err, "failed to listen")
}
defer func() {
if err := listener.Close(); err != nil {
zap.L().Error(
"failed to close listener",
zap.String("address", opts.GRPCBind),
zap.Error(err),
)
}
}()

grpcServer := grpc.NewServer()
grpcLogger := zap.L().Named("grpc")
serverStreamOpts := []grpc.StreamServerInterceptor{
grpc_recovery.StreamServerInterceptor(),
grpc_ctxtags.StreamServerInterceptor(),
grpc_zap.StreamServerInterceptor(grpcLogger),
grpc_recovery.StreamServerInterceptor(),
}
serverUnaryOpts := []grpc.UnaryServerInterceptor{
grpc_recovery.UnaryServerInterceptor(),
grpc_ctxtags.UnaryServerInterceptor(),
grpc_zap.UnaryServerInterceptor(grpcLogger),
grpc_recovery.UnaryServerInterceptor(),
}
grpcServer := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(serverStreamOpts...)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(serverUnaryOpts...)),
)
RegisterServerServer(grpcServer, &svc{})
if opts.WithReflection {
reflection.Register(grpcServer)
}

go func() {
defer grpcServer.GracefulStop()
<-ctx.Done()
}()

zap.L().Info("grpc server started", zap.String("bind", opts.GRPCBind))
grpcServer.Serve(listener)
return nil
zap.L().Info("starting gRPC server", zap.String("bind", opts.GRPCBind))
return grpcServer.Serve(listener)
}
Oops, something went wrong.

0 comments on commit 6fd644a

Please sign in to comment.