diff --git a/go.mod b/go.mod index 3972a7db8..1a9250e43 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,10 @@ require ( github.com/UnnoTed/fileb0x v1.1.4 // indirect github.com/cespare/reflex v0.2.0 // indirect github.com/go-chi/chi v4.0.2+incompatible + github.com/golang/protobuf v1.3.2 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/micro/cli/v2 v2.1.1 + github.com/micro/go-micro/v2 v2.0.0 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/ogier/pflag v0.0.1 // indirect github.com/oklog/run v1.0.0 diff --git a/go.sum b/go.sum index 3083637f6..c44798de3 100644 --- a/go.sum +++ b/go.sum @@ -487,6 +487,7 @@ github.com/micro/go-micro v1.18.0/go.mod h1:klwUJL1gkdY1MHFyz+fFJXn52dKcty4hoe95 github.com/micro/go-micro/v2 v2.0.0 h1:bMx549RwJ9Yuiui8cDVlfYhVNP8I8KBJTMyLthEXpRw= github.com/micro/go-micro/v2 v2.0.0/go.mod h1:v7QP5UhKRt37ixjJe8DouWmg0/eE6dltr5h0idJ9BpE= github.com/micro/go-plugins v1.5.1/go.mod h1:jcxejzJCAMH731cQHbS/hncyKe0rxAbzKkibj8glad4= +github.com/micro/go-plugins/wrapper/trace/opencensus/v2 v2.0.1 h1:7IkXfl94MdLZQwk0lNmu9Cg5WP42Zak9EtQMeN4SvVs= github.com/micro/go-plugins/wrapper/trace/opencensus/v2 v2.0.1/go.mod h1:QrkcwcDtIs2hIJpIEhozekyf6Rfz5C36kFI8+zzCpX0= github.com/micro/mdns v0.3.0 h1:bYycYe+98AXR3s8Nq5qvt6C573uFTDPIYzJemWON0QE= github.com/micro/mdns v0.3.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= diff --git a/pkg/command/server.go b/pkg/command/server.go index 31f8dce9d..af6cafecf 100644 --- a/pkg/command/server.go +++ b/pkg/command/server.go @@ -2,9 +2,9 @@ package command import ( "context" + "fmt" "os" "os/signal" - "strings" "time" "contrib.go.opencensus.io/exporter/jaeger" @@ -17,8 +17,7 @@ import ( "github.com/owncloud/ocis-thumbnails/pkg/config" "github.com/owncloud/ocis-thumbnails/pkg/flagset" "github.com/owncloud/ocis-thumbnails/pkg/metrics" - "github.com/owncloud/ocis-thumbnails/pkg/server/debug" - "github.com/owncloud/ocis-thumbnails/pkg/server/http" + "github.com/owncloud/ocis-thumbnails/pkg/server/grpc" "go.opencensus.io/stats/view" "go.opencensus.io/trace" ) @@ -30,10 +29,6 @@ func Server(cfg *config.Config) *cli.Command { Usage: "Start integrated server", Flags: flagset.ServerWithConfig(cfg), Before: func(c *cli.Context) error { - if cfg.HTTP.Root != "/" { - cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/") - } - return nil }, Action: func(c *cli.Context) error { @@ -131,72 +126,22 @@ func Server(cfg *config.Config) *cli.Command { defer cancel() - { - server, err := http.Server( - http.Logger(logger), - http.Context(ctx), - http.Config(cfg), - http.Metrics(metrics), - http.Flags(flagset.RootWithConfig(cfg)), - http.Flags(flagset.ServerWithConfig(cfg)), - ) + service := grpc.NewService( + grpc.Logger(logger), + grpc.Context(ctx), + grpc.Config(cfg), + grpc.Name(cfg.Server.Name), + grpc.Namespace(cfg.Server.Namespace), + grpc.Address(cfg.Server.Address), + grpc.Metrics(metrics), + ) - if err != nil { - logger.Info(). - Err(err). - Str("transport", "http"). - Msg("Failed to initialize server") - - return err - } - - gr.Add(func() error { - return server.Run() - }, func(_ error) { - logger.Info(). - Str("transport", "http"). - Msg("Shutting down server") - - cancel() - }) - } - - { - server, err := debug.Server( - debug.Logger(logger), - debug.Context(ctx), - debug.Config(cfg), - ) - - if err != nil { - logger.Info(). - Err(err). - Str("transport", "debug"). - Msg("Failed to initialize server") - - return err - } - - gr.Add(func() error { - return server.ListenAndServe() - }, func(_ error) { - ctx, timeout := context.WithTimeout(ctx, 5*time.Second) - - defer timeout() - defer cancel() - - if err := server.Shutdown(ctx); err != nil { - logger.Info(). - Err(err). - Str("transport", "debug"). - Msg("Failed to shutdown server") - } else { - logger.Info(). - Str("transport", "debug"). - Msg("Shutting down server") - } - }) - } + gr.Add(func() error { + return service.Run() + }, func(_ error) { + fmt.Println("shutting down grpc server") + cancel() + }) { stop := make(chan os.Signal, 1) diff --git a/pkg/config/config.go b/pkg/config/config.go index a5bc260e0..e84b514b9 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -15,11 +15,11 @@ type Debug struct { Zpages bool } -// HTTP defines the available http configuration. -type HTTP struct { - Addr string +// Server defines the available server configuration. +type Server struct { + Name string Namespace string - Root string + Address string } // Tracing defines the available tracing configuration. @@ -36,7 +36,7 @@ type Config struct { File string Log Log Debug Debug - HTTP HTTP + Server Server Tracing Tracing FileSystemStorage FileSystemStorage WebDavSource WebDavSource diff --git a/pkg/flagset/flagset.go b/pkg/flagset/flagset.go index 04eae4706..2f34817b1 100644 --- a/pkg/flagset/flagset.go +++ b/pkg/flagset/flagset.go @@ -117,25 +117,25 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { Destination: &cfg.Debug.Zpages, }, &cli.StringFlag{ - Name: "http-addr", + Name: "grpc-name", + Value: "thumbnails", + Usage: "Name of the service", + EnvVars: []string{"THUMBNAILS_GRPC_NAME"}, + Destination: &cfg.Server.Name, + }, + &cli.StringFlag{ + Name: "grpc-addr", Value: "0.0.0.0:9185", - Usage: "Address to bind http server", - EnvVars: []string{"THUMBNAILS_HTTP_ADDR"}, - Destination: &cfg.HTTP.Addr, + Usage: "Address to bind grpc server", + EnvVars: []string{"THUMBNAILS_GRPC_ADDR"}, + Destination: &cfg.Server.Address, }, &cli.StringFlag{ - Name: "http-namespace", - Value: "com.owncloud.web", - Usage: "Set the base namespace for the http namespace", - EnvVars: []string{"THUMBNAILS_HTTP_NAMESPACE"}, - Destination: &cfg.HTTP.Namespace, - }, - &cli.StringFlag{ - Name: "http-root", - Value: "/", - Usage: "Root path of http server", - EnvVars: []string{"THUMBNAILS_HTTP_ROOT"}, - Destination: &cfg.HTTP.Root, + Name: "grpc-namespace", + Value: "com.owncloud.api", + Usage: "Set the base namespace for the grpc namespace", + EnvVars: []string{"THUMBNAILS_GRPC_NAMESPACE"}, + Destination: &cfg.Server.Namespace, }, &cli.StringFlag{ Name: "filesystemstorage-root", diff --git a/pkg/proto/v0/thumbnails.pb.go b/pkg/proto/v0/thumbnails.pb.go new file mode 100644 index 000000000..8fb6ad6da --- /dev/null +++ b/pkg/proto/v0/thumbnails.pb.go @@ -0,0 +1,195 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: pkg/proto/v0/thumbnails.proto + +package proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type GetRequest_FileType int32 + +const ( + GetRequest_PNG GetRequest_FileType = 0 + GetRequest_JPG GetRequest_FileType = 1 +) + +var GetRequest_FileType_name = map[int32]string{ + 0: "PNG", + 1: "JPG", +} + +var GetRequest_FileType_value = map[string]int32{ + "PNG": 0, + "JPG": 1, +} + +func (x GetRequest_FileType) String() string { + return proto.EnumName(GetRequest_FileType_name, int32(x)) +} + +func (GetRequest_FileType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e354cb4f8a62b6c2, []int{0, 0} +} + +type GetRequest struct { + Filepath string `protobuf:"bytes,1,opt,name=filepath,proto3" json:"filepath,omitempty"` + Filetype GetRequest_FileType `protobuf:"varint,2,opt,name=filetype,proto3,enum=com.owncloud.ocis.thumbnails.v0.GetRequest_FileType" json:"filetype,omitempty"` + Etag string `protobuf:"bytes,3,opt,name=etag,proto3" json:"etag,omitempty"` + Width int32 `protobuf:"varint,4,opt,name=width,proto3" json:"width,omitempty"` + Height int32 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Authorization string `protobuf:"bytes,6,opt,name=authorization,proto3" json:"authorization,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetRequest) Reset() { *m = GetRequest{} } +func (m *GetRequest) String() string { return proto.CompactTextString(m) } +func (*GetRequest) ProtoMessage() {} +func (*GetRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_e354cb4f8a62b6c2, []int{0} +} + +func (m *GetRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetRequest.Unmarshal(m, b) +} +func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) +} +func (m *GetRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetRequest.Merge(m, src) +} +func (m *GetRequest) XXX_Size() int { + return xxx_messageInfo_GetRequest.Size(m) +} +func (m *GetRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetRequest proto.InternalMessageInfo + +func (m *GetRequest) GetFilepath() string { + if m != nil { + return m.Filepath + } + return "" +} + +func (m *GetRequest) GetFiletype() GetRequest_FileType { + if m != nil { + return m.Filetype + } + return GetRequest_PNG +} + +func (m *GetRequest) GetEtag() string { + if m != nil { + return m.Etag + } + return "" +} + +func (m *GetRequest) GetWidth() int32 { + if m != nil { + return m.Width + } + return 0 +} + +func (m *GetRequest) GetHeight() int32 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *GetRequest) GetAuthorization() string { + if m != nil { + return m.Authorization + } + return "" +} + +type GetResponse struct { + Thumbnail []byte `protobuf:"bytes,1,opt,name=thumbnail,proto3" json:"thumbnail,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetResponse) Reset() { *m = GetResponse{} } +func (m *GetResponse) String() string { return proto.CompactTextString(m) } +func (*GetResponse) ProtoMessage() {} +func (*GetResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_e354cb4f8a62b6c2, []int{1} +} + +func (m *GetResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetResponse.Unmarshal(m, b) +} +func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) +} +func (m *GetResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetResponse.Merge(m, src) +} +func (m *GetResponse) XXX_Size() int { + return xxx_messageInfo_GetResponse.Size(m) +} +func (m *GetResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetResponse proto.InternalMessageInfo + +func (m *GetResponse) GetThumbnail() []byte { + if m != nil { + return m.Thumbnail + } + return nil +} + +func init() { + proto.RegisterEnum("com.owncloud.ocis.thumbnails.v0.GetRequest_FileType", GetRequest_FileType_name, GetRequest_FileType_value) + proto.RegisterType((*GetRequest)(nil), "com.owncloud.ocis.thumbnails.v0.GetRequest") + proto.RegisterType((*GetResponse)(nil), "com.owncloud.ocis.thumbnails.v0.GetResponse") +} + +func init() { proto.RegisterFile("pkg/proto/v0/thumbnails.proto", fileDescriptor_e354cb4f8a62b6c2) } + +var fileDescriptor_e354cb4f8a62b6c2 = []byte{ + // 300 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x4f, 0x4f, 0xc2, 0x40, + 0x10, 0xc5, 0x2d, 0x50, 0xfe, 0x8c, 0x68, 0xc8, 0xc4, 0x98, 0x86, 0x60, 0x24, 0xc4, 0x03, 0x09, + 0x66, 0x21, 0xe8, 0x27, 0xf0, 0x60, 0x13, 0x0f, 0x86, 0x54, 0x4e, 0xde, 0x4a, 0x19, 0xd9, 0x8d, + 0xa5, 0xbb, 0xd2, 0x29, 0x04, 0x13, 0x13, 0x3f, 0xba, 0x71, 0x2b, 0x45, 0x4f, 0xea, 0x69, 0xe7, + 0xfd, 0x76, 0xf2, 0x66, 0xf6, 0x2d, 0x9c, 0x99, 0xe7, 0xc5, 0xd0, 0xac, 0x34, 0xeb, 0xe1, 0x7a, + 0x34, 0x64, 0x99, 0x2d, 0x67, 0x49, 0xa8, 0xe2, 0x54, 0x58, 0x86, 0xe7, 0x91, 0x5e, 0x0a, 0xbd, + 0x49, 0xa2, 0x58, 0x67, 0x73, 0xa1, 0x23, 0x95, 0x8a, 0x6f, 0x3d, 0xeb, 0x51, 0xef, 0xbd, 0x04, + 0xe0, 0x13, 0x07, 0xf4, 0x92, 0x51, 0xca, 0xd8, 0x86, 0xfa, 0x93, 0x8a, 0xc9, 0x84, 0x2c, 0x3d, + 0xa7, 0xeb, 0xf4, 0x1b, 0x41, 0xa1, 0x71, 0x92, 0xdf, 0xf1, 0xd6, 0x90, 0x57, 0xea, 0x3a, 0xfd, + 0xe3, 0xf1, 0xb5, 0xf8, 0xc5, 0x5e, 0xec, 0xad, 0xc5, 0xad, 0x8a, 0x69, 0xba, 0x35, 0x14, 0x14, + 0x2e, 0x88, 0x50, 0x21, 0x0e, 0x17, 0x5e, 0xd9, 0x4e, 0xb2, 0x35, 0x9e, 0x80, 0xbb, 0x51, 0x73, + 0x96, 0x5e, 0xa5, 0xeb, 0xf4, 0xdd, 0x20, 0x17, 0x78, 0x0a, 0x55, 0x49, 0x6a, 0x21, 0xd9, 0x73, + 0x2d, 0xfe, 0x52, 0x78, 0x01, 0x47, 0x61, 0xc6, 0x52, 0xaf, 0xd4, 0x6b, 0xc8, 0x4a, 0x27, 0x5e, + 0xd5, 0x5a, 0xfd, 0x84, 0xbd, 0x0e, 0xd4, 0x77, 0xd3, 0xb1, 0x06, 0xe5, 0xc9, 0xbd, 0xdf, 0x3a, + 0xf8, 0x2c, 0xee, 0x26, 0x7e, 0xcb, 0xe9, 0x0d, 0xe0, 0xd0, 0xae, 0x99, 0x1a, 0x9d, 0xa4, 0x84, + 0x1d, 0x68, 0x14, 0x6f, 0xb0, 0x19, 0x34, 0x83, 0x3d, 0x18, 0xbf, 0x41, 0x6b, 0xba, 0x13, 0x0f, + 0xb4, 0x5a, 0xab, 0x88, 0x50, 0x41, 0xd3, 0x27, 0x2e, 0x30, 0x0e, 0xfe, 0x11, 0x4b, 0xfb, 0xf2, + 0x6f, 0xcd, 0xf9, 0x72, 0x37, 0xb5, 0x47, 0xd7, 0x7e, 0xec, 0xac, 0x6a, 0x8f, 0xab, 0x8f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x54, 0x8e, 0xdc, 0xb1, 0x00, 0x02, 0x00, 0x00, +} diff --git a/pkg/proto/v0/thumbnails.pb.micro.go b/pkg/proto/v0/thumbnails.pb.micro.go new file mode 100644 index 000000000..9533ba8fa --- /dev/null +++ b/pkg/proto/v0/thumbnails.pb.micro.go @@ -0,0 +1,85 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: pkg/proto/v0/thumbnails.proto + +package proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + client "github.com/micro/go-micro/v2/client" + server "github.com/micro/go-micro/v2/server" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ client.Option +var _ server.Option + +// Client API for ThumbnailService service + +type ThumbnailService interface { + GetThumbnail(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) +} + +type thumbnailService struct { + c client.Client + name string +} + +func NewThumbnailService(name string, c client.Client) ThumbnailService { + return &thumbnailService{ + c: c, + name: name, + } +} + +func (c *thumbnailService) GetThumbnail(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) { + req := c.c.NewRequest(c.name, "ThumbnailService.GetThumbnail", in) + out := new(GetResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for ThumbnailService service + +type ThumbnailServiceHandler interface { + GetThumbnail(context.Context, *GetRequest, *GetResponse) error +} + +func RegisterThumbnailServiceHandler(s server.Server, hdlr ThumbnailServiceHandler, opts ...server.HandlerOption) error { + type thumbnailService interface { + GetThumbnail(ctx context.Context, in *GetRequest, out *GetResponse) error + } + type ThumbnailService struct { + thumbnailService + } + h := &thumbnailServiceHandler{hdlr} + return s.Handle(s.NewHandler(&ThumbnailService{h}, opts...)) +} + +type thumbnailServiceHandler struct { + ThumbnailServiceHandler +} + +func (h *thumbnailServiceHandler) GetThumbnail(ctx context.Context, in *GetRequest, out *GetResponse) error { + return h.ThumbnailServiceHandler.GetThumbnail(ctx, in, out) +} diff --git a/pkg/proto/v0/thumbnails.proto b/pkg/proto/v0/thumbnails.proto new file mode 100644 index 000000000..94f252914 --- /dev/null +++ b/pkg/proto/v0/thumbnails.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package com.owncloud.ocis.thumbnails.v0; +option go_package = "proto"; + +service ThumbnailService { + rpc GetThumbnail(GetRequest) returns (GetResponse); +} + +message GetRequest { + string filepath = 1; + enum FileType { + PNG = 0; + JPG = 1; + } + FileType filetype = 2; + string etag = 3; + int32 width = 4; + int32 height = 5; + string authorization = 6; +} + +message GetResponse { + bytes thumbnail = 1; +} \ No newline at end of file diff --git a/pkg/server/debug/option.go b/pkg/server/debug/option.go deleted file mode 100644 index b07f8b6ad..000000000 --- a/pkg/server/debug/option.go +++ /dev/null @@ -1,50 +0,0 @@ -package debug - -import ( - "context" - - "github.com/owncloud/ocis-thumbnails/pkg/config" - "github.com/owncloud/ocis-pkg/v2/log" -) - -// Option defines a single option function. -type Option func(o *Options) - -// Options defines the available options for this package. -type Options struct { - Logger log.Logger - Context context.Context - Config *config.Config -} - -// newOptions initializes the available default options. -func newOptions(opts ...Option) Options { - opt := Options{} - - for _, o := range opts { - o(&opt) - } - - return opt -} - -// Logger provides a function to set the logger option. -func Logger(val log.Logger) Option { - return func(o *Options) { - o.Logger = val - } -} - -// Context provides a function to set the context option. -func Context(val context.Context) Option { - return func(o *Options) { - o.Context = val - } -} - -// Config provides a function to set the config option. -func Config(val *config.Config) Option { - return func(o *Options) { - o.Config = val - } -} diff --git a/pkg/server/debug/server.go b/pkg/server/debug/server.go deleted file mode 100644 index 0ac9f253a..000000000 --- a/pkg/server/debug/server.go +++ /dev/null @@ -1,51 +0,0 @@ -package debug - -import ( - "io" - "net/http" - - "github.com/owncloud/ocis-thumbnails/pkg/config" - "github.com/owncloud/ocis-thumbnails/pkg/version" - "github.com/owncloud/ocis-pkg/v2/service/debug" -) - -// Server initializes the debug service and server. -func Server(opts ...Option) (*http.Server, error) { - options := newOptions(opts...) - - return debug.NewService( - debug.Logger(options.Logger), - debug.Name("ocis-thumbnails"), - debug.Version(version.String), - debug.Address(options.Config.Debug.Addr), - debug.Token(options.Config.Debug.Token), - debug.Pprof(options.Config.Debug.Pprof), - debug.Zpages(options.Config.Debug.Zpages), - debug.Health(health(options.Config)), - debug.Ready(ready(options.Config)), - ), nil -} - -// health implements the health check. -func health(cfg *config.Config) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - - // TODO(tboerger): check if services are up and running - - io.WriteString(w, http.StatusText(http.StatusOK)) - } -} - -// ready implements the ready check. -func ready(cfg *config.Config) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - - // TODO(tboerger): check if services are up and running - - io.WriteString(w, http.StatusText(http.StatusOK)) - } -} diff --git a/pkg/server/http/option.go b/pkg/server/grpc/option.go similarity index 80% rename from pkg/server/http/option.go rename to pkg/server/grpc/option.go index 5712bc5f2..569480ff6 100644 --- a/pkg/server/http/option.go +++ b/pkg/server/grpc/option.go @@ -1,12 +1,11 @@ -package http +package grpc import ( "context" - "github.com/micro/cli/v2" + "github.com/owncloud/ocis-pkg/v2/log" "github.com/owncloud/ocis-thumbnails/pkg/config" "github.com/owncloud/ocis-thumbnails/pkg/metrics" - "github.com/owncloud/ocis-pkg/v2/log" ) // Option defines a single option function. @@ -14,12 +13,13 @@ type Option func(o *Options) // Options defines the available options for this package. type Options struct { - Namespace string + Name string + Address string Logger log.Logger Context context.Context Config *config.Config Metrics *metrics.Metrics - Flags []cli.Flag + Namespace string } // newOptions initializes the available default options. @@ -40,6 +40,20 @@ func Logger(val log.Logger) Option { } } +// Name provides a name for the service. +func Name(val string) Option { + return func(o *Options) { + o.Name = val + } +} + +// Address provides an address for the service. +func Address(val string) Option { + return func(o *Options) { + o.Address = val + } +} + // Context provides a function to set the context option. func Context(val context.Context) Option { return func(o *Options) { @@ -61,14 +75,7 @@ func Metrics(val *metrics.Metrics) Option { } } -// Flags provides a function to set the flags option. -func Flags(val []cli.Flag) Option { - return func(o *Options) { - o.Flags = append(o.Flags, val...) - } -} - -// Namespace provides a function to set the Namespace option. +// Namespace provides a function to set the namespace option. func Namespace(val string) Option { return func(o *Options) { o.Namespace = val diff --git a/pkg/server/grpc/server.go b/pkg/server/grpc/server.go new file mode 100644 index 000000000..96c64e1d0 --- /dev/null +++ b/pkg/server/grpc/server.go @@ -0,0 +1,39 @@ +package grpc + +import ( + "github.com/owncloud/ocis-pkg/v2/service/grpc" + "github.com/owncloud/ocis-thumbnails/pkg/proto/v0" + svc "github.com/owncloud/ocis-thumbnails/pkg/service/v0" + "github.com/owncloud/ocis-thumbnails/pkg/version" +) + +// NewService initializes the grpc service and server. +func NewService(opts ...Option) grpc.Service { + options := newOptions(opts...) + + service := grpc.NewService( + grpc.Logger(options.Logger), + grpc.Namespace(options.Namespace), + grpc.Name(options.Name), + grpc.Version(version.String), + grpc.Address(options.Address), + grpc.Context(options.Context), + ) + + var thumbnail proto.ThumbnailServiceHandler + { + thumbnail = svc.NewService( + svc.Config(options.Config), + ) + thumbnail = svc.NewInstrument(thumbnail, options.Metrics) + thumbnail = svc.NewLogging(thumbnail, options.Logger) + } + + proto.RegisterThumbnailServiceHandler( + service.Server(), + thumbnail, + ) + + service.Init() + return service +} diff --git a/pkg/server/http/server.go b/pkg/server/http/server.go deleted file mode 100644 index 66607a2fc..000000000 --- a/pkg/server/http/server.go +++ /dev/null @@ -1,56 +0,0 @@ -package http - -import ( - svc "github.com/owncloud/ocis-thumbnails/pkg/service/v0" - "github.com/owncloud/ocis-thumbnails/pkg/version" - "github.com/owncloud/ocis-pkg/v2/middleware" - "github.com/owncloud/ocis-pkg/v2/service/http" -) - -// Server initializes the http service and server. -func Server(opts ...Option) (http.Service, error) { - options := newOptions(opts...) - - service := http.NewService( - http.Logger(options.Logger), - http.Name("thumbnails"), - http.Version(version.String), - http.Namespace(options.Config.HTTP.Namespace), - http.Address(options.Config.HTTP.Addr), - http.Context(options.Context), - http.Flags(options.Flags...), - ) - - handle := svc.NewService( - svc.Logger(options.Logger), - svc.Config(options.Config), - svc.Middleware( - middleware.RealIP, - middleware.RequestID, - middleware.Cache, - middleware.Cors, - middleware.Secure, - middleware.Version( - "thumbnails", - version.String, - ), - middleware.Logger( - options.Logger, - ), - ), - ) - - { - handle = svc.NewInstrument(handle, options.Metrics) - handle = svc.NewLogging(handle, options.Logger) - handle = svc.NewTracing(handle) - } - - service.Handle( - "/", - handle, - ) - - service.Init() - return service, nil -} diff --git a/pkg/service/v0/instrument.go b/pkg/service/v0/instrument.go index 9c3a6d999..86ab4e6a4 100644 --- a/pkg/service/v0/instrument.go +++ b/pkg/service/v0/instrument.go @@ -1,13 +1,14 @@ package svc import ( - "net/http" + "context" "github.com/owncloud/ocis-thumbnails/pkg/metrics" + v0proto "github.com/owncloud/ocis-thumbnails/pkg/proto/v0" ) // NewInstrument returns a service that instruments metrics. -func NewInstrument(next Service, metrics *metrics.Metrics) Service { +func NewInstrument(next v0proto.ThumbnailServiceHandler, metrics *metrics.Metrics) v0proto.ThumbnailServiceHandler { return instrument{ next: next, metrics: metrics, @@ -15,16 +16,11 @@ func NewInstrument(next Service, metrics *metrics.Metrics) Service { } type instrument struct { - next Service + next v0proto.ThumbnailServiceHandler metrics *metrics.Metrics } -// ServeHTTP implements the Service interface. -func (i instrument) ServeHTTP(w http.ResponseWriter, r *http.Request) { - i.next.ServeHTTP(w, r) -} - -// Dummy implements the Service interface. -func (i instrument) Thumbnails(w http.ResponseWriter, r *http.Request) { - i.next.Thumbnails(w, r) +// GetThumbnail implements the ThumbnailServiceHandler interface. +func (i instrument) GetThumbnail(ctx context.Context, req *v0proto.GetRequest, rsp *v0proto.GetResponse) error { + return i.next.GetThumbnail(ctx, req, rsp) } diff --git a/pkg/service/v0/logging.go b/pkg/service/v0/logging.go index a439f1efd..90f2916d9 100644 --- a/pkg/service/v0/logging.go +++ b/pkg/service/v0/logging.go @@ -1,13 +1,14 @@ package svc import ( - "net/http" + "context" "github.com/owncloud/ocis-pkg/v2/log" + v0proto "github.com/owncloud/ocis-thumbnails/pkg/proto/v0" ) // NewLogging returns a service that logs messages. -func NewLogging(next Service, logger log.Logger) Service { +func NewLogging(next v0proto.ThumbnailServiceHandler, logger log.Logger) v0proto.ThumbnailServiceHandler { return logging{ next: next, logger: logger, @@ -15,16 +16,11 @@ func NewLogging(next Service, logger log.Logger) Service { } type logging struct { - next Service + next v0proto.ThumbnailServiceHandler logger log.Logger } -// ServeHTTP implements the Service interface. -func (l logging) ServeHTTP(w http.ResponseWriter, r *http.Request) { - l.next.ServeHTTP(w, r) -} - -// Dummy implements the Service interface. -func (l logging) Thumbnails(w http.ResponseWriter, r *http.Request) { - l.next.Thumbnails(w, r) +// GetThumbnail implements the ThumbnailServiceHandler interface. +func (l logging) GetThumbnail(ctx context.Context, req *v0proto.GetRequest, rsp *v0proto.GetResponse) error { + return l.next.GetThumbnail(ctx, req, rsp) } diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index 5ae4cb095..b9a6700ac 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -2,33 +2,20 @@ package svc import ( "context" - "net/http" - "strconv" + "fmt" - "github.com/go-chi/chi" "github.com/owncloud/ocis-pkg/v2/log" - "github.com/owncloud/ocis-thumbnails/pkg/config" + v0proto "github.com/owncloud/ocis-thumbnails/pkg/proto/v0" "github.com/owncloud/ocis-thumbnails/pkg/thumbnails" "github.com/owncloud/ocis-thumbnails/pkg/thumbnails/imgsource" "github.com/owncloud/ocis-thumbnails/pkg/thumbnails/storage" ) -// Service defines the extension handlers. -type Service interface { - ServeHTTP(http.ResponseWriter, *http.Request) - Thumbnails(http.ResponseWriter, *http.Request) -} - // NewService returns a service implementation for Service. -func NewService(opts ...Option) Service { +func NewService(opts ...Option) v0proto.ThumbnailServiceHandler { options := newOptions(opts...) - m := chi.NewMux() - m.Use(options.Middleware...) - svc := Thumbnail{ - config: options.Config, - mux: m, manager: thumbnails.NewSimpleManager( storage.NewFileSystemStorage( options.Config.FileSystemStorage, @@ -40,77 +27,52 @@ func NewService(opts ...Option) Service { logger: options.Logger, } - m.Route(options.Config.HTTP.Root, func(r chi.Router) { - r.Get("/thumbnails", svc.Thumbnails) - }) - return svc } -// Thumbnail implements the business logic for Service. +// Thumbnail implements the GRPC handler. type Thumbnail struct { - config *config.Config - mux *chi.Mux manager thumbnails.Manager source imgsource.Source logger log.Logger } -// ServeHTTP implements the Service interface. -func (g Thumbnail) ServeHTTP(w http.ResponseWriter, r *http.Request) { - g.mux.ServeHTTP(w, r) -} - -// Thumbnails provides the endpoint to retrieve a thumbnail for an image -func (g Thumbnail) Thumbnails(w http.ResponseWriter, r *http.Request) { - query := r.URL.Query() - width, _ := strconv.Atoi(query.Get("width")) - height, _ := strconv.Atoi(query.Get("height")) - fileType := query.Get("type") - filePath := query.Get("file_path") - etag := query.Get("etag") - - encoder := thumbnails.EncoderForType(fileType) +// GetThumbnail retrieves a thumbnail for an image +func (g Thumbnail) GetThumbnail(ctx context.Context, req *v0proto.GetRequest, rsp *v0proto.GetResponse) error { + encoder := thumbnails.EncoderForType(req.Filetype.String()) if encoder == nil { // TODO: better error responses - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("can't encode that")) - return + return fmt.Errorf("can't be encoded. filetype %s not supported", req.Filetype.String()) } - ctx := thumbnails.Context{ - Width: width, - Height: height, - ImagePath: filePath, + tCtx := thumbnails.Context{ + Width: int(req.Width), + Height: int(req.Height), + ImagePath: req.Filepath, Encoder: encoder, - ETag: etag, + ETag: req.Etag, } - thumbnail := g.manager.GetStored(ctx) + thumbnail := g.manager.GetStored(tCtx) if thumbnail != nil { - w.Write(thumbnail) - return + rsp.Thumbnail = thumbnail + return nil } - auth := r.Header.Get("Authorization") - sCtx := context.WithValue(r.Context(), imgsource.WebDavAuth, auth) + auth := req.Authorization + sCtx := context.WithValue(ctx, imgsource.WebDavAuth, auth) // TODO: clean up error handling - img, err := g.source.Get(sCtx, ctx.ImagePath) + img, err := g.source.Get(sCtx, tCtx.ImagePath) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - return + return err } if img == nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("img is nil")) - return + return fmt.Errorf("could not retrieve image") } - thumbnail, err = g.manager.Get(ctx, img) + thumbnail, err = g.manager.Get(tCtx, img) if err != nil { - w.Write([]byte(err.Error())) - return + return err } - w.WriteHeader(http.StatusCreated) - w.Write(thumbnail) + rsp.Thumbnail = thumbnail + return nil } diff --git a/pkg/service/v0/tracing.go b/pkg/service/v0/tracing.go index 444afd3ec..33d4f01cc 100644 --- a/pkg/service/v0/tracing.go +++ b/pkg/service/v0/tracing.go @@ -1,26 +1,23 @@ package svc import ( - "net/http" + "context" + + v0proto "github.com/owncloud/ocis-thumbnails/pkg/proto/v0" ) // NewTracing returns a service that instruments traces. -func NewTracing(next Service) Service { +func NewTracing(next v0proto.ThumbnailServiceHandler) v0proto.ThumbnailServiceHandler { return tracing{ next: next, } } type tracing struct { - next Service + next v0proto.ThumbnailServiceHandler } -// ServeHTTP implements the Service interface. -func (t tracing) ServeHTTP(w http.ResponseWriter, r *http.Request) { - t.next.ServeHTTP(w, r) -} - -// Dummy implements the Service interface. -func (t tracing) Thumbnails(w http.ResponseWriter, r *http.Request) { - t.next.Thumbnails(w, r) +// GetThumbnail implements the ThumbnailServiceHandler interface. +func (t tracing) GetThumbnail(ctx context.Context, req *v0proto.GetRequest, rsp *v0proto.GetResponse) error { + return t.next.GetThumbnail(ctx, req, rsp) }