func serve(opts []grpc.ServerOption) { grpcServer := grpc.NewServer(opts...) pb.RegisterYourServiceServer(grpcServer, newServer()) ctx := context.Background() name := fmt.Sprintf("localhost:%d", *port) dcreds, err := credentials.NewClientTLSFromFile(*certFile, name) if err != nil { fmt.Printf("serve: %v\n", err) return } dopts := []grpc.DialOption{grpc.WithTransportCredentials(dcreds)} mux := runtime.NewServeMux() err = pb.RegisterYourServiceHandlerFromEndpoint(ctx, mux, name, dopts) if err != nil { fmt.Printf("serve: %v\n", err) return } err = http.ListenAndServeTLS(fmt.Sprintf(":%d", *port), *certFile, *keyFile, grpcHandlerFunc(grpcServer, mux)) if err != nil { log.Fatal("ListenAndServe: ", err) } return }
func registerGateway(addr string, opts []grpc.DialOption) (*gw.ServeMux, error) { gwmux := gw.NewServeMux() err := pb.RegisterKVHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } err = pb.RegisterWatchHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } err = pb.RegisterLeaseHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } err = pb.RegisterClusterHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } err = pb.RegisterMaintenanceHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } err = pb.RegisterAuthHandlerFromEndpoint(context.Background(), gwmux, addr, opts) if err != nil { return nil, err } return gwmux, nil }
// NewHttpGrpcHandler - Will return back new HTTP GRPC handler func NewHttpGrpcHandler(serv services.Servicer, logger *logging.Entry, handler func(context.Context, *runtime.ServeMux, *grpc.ClientConn) error) (*HttpGrpcHandler, error) { grpcAddr, ok := serv.GetOptions().Get("grpc-addr") if !ok { return nil, errors.New("In order to register new grpc http handler `grpc-addr` must be set.") } certFile, ok := serv.GetOptions().Get("grpc-tls-cert") if !ok { return nil, errors.New("In order to register new grpc http handler `grpc-tls-cert` must be set.") } certDomain, ok := serv.GetOptions().Get("grpc-tls-domain") if !ok { return nil, errors.New("In order to register new grpc http handler `grpc-tls-domain` must be set.") } httpgrpc := &HttpGrpcHandler{ ctx: context.Background(), ServeMux: runtime.NewServeMux(), Servicer: serv, Entry: logger, GrpcAddr: grpcAddr, CertFile: certFile, CertDomain: certDomain, } // Will register provider handler (protocol buffer client) and start grpc.Dial if err := httpgrpc.RegisterHandlerTLS(handler); err != nil { return nil, err } return httpgrpc, nil }
func main() { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() err := player.RegisterPlayerHandlerFromEndpoint(ctx, mux, ":2015") if err != nil { log.Fatal("Couldn't register: ", err) } http.ListenAndServe(":2017", mux) }
func run() error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint) if err != nil { return err } http.ListenAndServe(":8080", mux) return nil }
func Run() error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() err := RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint) if err != nil { return err } err = RegisterABitOfEverythingServiceHandlerFromEndpoint(ctx, mux, *abeEndpoint) if err != nil { return err } http.ListenAndServe(":8080", mux) return nil }
// newAdminServer allocates and returns a new REST server for // administrative APIs. func newAdminServer(s *Server) *adminServer { server := &adminServer{ ServeMux: http.NewServeMux(), server: s, } // Register HTTP handlers. server.ServeMux.HandleFunc(debugEndpoint, server.handleDebug) // TODO(cdo): Move quit and health endpoints to gRPC. server.ServeMux.HandleFunc(quitPath, server.handleQuit) server.ServeMux.HandleFunc(healthPath, server.handleHealth) // Initialize grpc-gateway mux and context. server.gwMux = gwruntime.NewServeMux() server.gwCtx, server.gwCancel = context.WithCancel(context.Background()) return server }
func runRest() error { ctx := context.Background() mux := runtime.NewServeMux() client, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", *grpcPort)) if err != nil { return err } err = pb_dpl.RegisterDeploymentsHandler(ctx, mux, client) if err != nil { return err } go func() { bindTo := fmt.Sprintf(":%d", *restPort) logger.Infof("REST litening %v", bindTo) http.ListenAndServe(bindTo, mux) }() return nil }
// newAdminServer allocates and returns a new REST server for // administrative APIs. func newAdminServer(db *client.DB, stopper *stop.Stopper, sqlExecutor *sql.Executor) *adminServer { server := &adminServer{ db: db, stopper: stopper, sqlExecutor: sqlExecutor, ServeMux: http.NewServeMux(), } // Register HTTP handlers. server.ServeMux.HandleFunc(debugEndpoint, server.handleDebug) // TODO(cdo): Move quit and health endpoints to gRPC. server.ServeMux.HandleFunc(quitPath, server.handleQuit) server.ServeMux.HandleFunc(healthPath, server.handleHealth) // Initialize grpc-gateway mux and context. server.gwMux = gwruntime.NewServeMux() server.gwCtx, server.gwCancel = context.WithCancel(context.Background()) return server }
func Run(address string, opts ...runtime.ServeMuxOption) error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux(opts...) err := examplepb.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint) if err != nil { return err } err = examplepb.RegisterABitOfEverythingServiceHandlerFromEndpoint(ctx, mux, *abeEndpoint) if err != nil { return err } err = examplepb.RegisterFlowCombinationHandlerFromEndpoint(ctx, mux, *flowEndpoint) if err != nil { return err } http.ListenAndServe(address, mux) return nil }
// ServeWithHTTP serves stuff. func ServeWithHTTP( registerFunc func(*grpc.Server), httpRegisterFunc func(context.Context, *runtime.ServeMux, *grpc.ClientConn) error, options ServeWithHTTPOptions, serveEnv ServeEnv, handlerEnv pkghttp.HandlerEnv, ) (retErr error) { defer func(start time.Time) { logServerFinished(start, retErr) }(time.Now()) if registerFunc == nil || httpRegisterFunc == nil { return ErrMustSpecifyRegisterFunc } if serveEnv.GRPCPort == 0 { serveEnv.GRPCPort = 7070 } if handlerEnv.Port == 0 { handlerEnv.Port = 8080 } grpcServer := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint32)) registerFunc(grpcServer) if options.Version != nil { protoversion.RegisterAPIServer(grpcServer, protoversion.NewAPIServer(options.Version, protoversion.APIServerOptions{})) } listener, err := net.Listen("tcp", fmt.Sprintf(":%d", serveEnv.GRPCPort)) if err != nil { return err } grpcErrC := make(chan error) go func() { grpcErrC <- grpcServer.Serve(listener) }() time.Sleep(1 * time.Second) ctx, cancel := context.WithCancel(context.Background()) conn, err := grpc.Dial(fmt.Sprintf("0.0.0.0:%d", serveEnv.GRPCPort), grpc.WithInsecure()) if err != nil { cancel() return err } go func() { <-ctx.Done() _ = conn.Close() }() mux := runtime.NewServeMux() if options.Version != nil { if err := protoversion.RegisterAPIHandler(ctx, mux, conn); err != nil { cancel() return err } } if err := httpRegisterFunc(ctx, mux, conn); err != nil { cancel() return err } var handler http.Handler = mux if options.HTTPHandlerModifier != nil { handler, err = options.HTTPHandlerModifier(mux) if err != nil { cancel() return err } } httpErrC := make(chan error) go func() { httpErrC <- pkghttp.ListenAndServe(handler, handlerEnv) }() protolion.Info( &ServerStarted{ Port: uint32(serveEnv.GRPCPort), HttpPort: uint32(handlerEnv.Port), }, ) var errs []error grpcStopped := false for i := 0; i < 2; i++ { select { case grpcErr := <-grpcErrC: if grpcErr != nil { errs = append(errs, fmt.Errorf("grpc error: %s", grpcErr.Error())) } grpcStopped = true case httpErr := <-httpErrC: if httpErr != nil { errs = append(errs, fmt.Errorf("http error: %s", httpErr.Error())) } if !grpcStopped { grpcServer.Stop() _ = listener.Close() grpcStopped = true } } } if len(errs) > 0 { return fmt.Errorf("%v", errs) } return nil }
func TestMuxServeHTTP(t *testing.T) { type stubPattern struct { method string ops []int pool []string } for _, spec := range []struct { patterns []stubPattern reqMethod string reqPath string headers map[string]string respStatus int respContent string }{ { patterns: nil, reqMethod: "GET", reqPath: "/", respStatus: http.StatusNotFound, }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "GET", reqPath: "/foo", respStatus: http.StatusOK, respContent: "GET /foo", }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "GET", reqPath: "/bar", respStatus: http.StatusNotFound, }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, { method: "GET", ops: []int{int(utilities.OpPush), 0}, }, }, reqMethod: "GET", reqPath: "/foo", respStatus: http.StatusOK, respContent: "GET /foo", }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, { method: "POST", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "POST", reqPath: "/foo", respStatus: http.StatusOK, respContent: "POST /foo", }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "DELETE", reqPath: "/foo", respStatus: http.StatusMethodNotAllowed, }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "POST", reqPath: "/foo", headers: map[string]string{ "Content-Type": "application/x-www-form-urlencoded", }, respStatus: http.StatusOK, respContent: "GET /foo", }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, { method: "POST", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "POST", reqPath: "/foo", headers: map[string]string{ "Content-Type": "application/x-www-form-urlencoded", "X-HTTP-Method-Override": "GET", }, respStatus: http.StatusOK, respContent: "GET /foo", }, { patterns: []stubPattern{ { method: "GET", ops: []int{int(utilities.OpLitPush), 0}, pool: []string{"foo"}, }, }, reqMethod: "POST", reqPath: "/foo", headers: map[string]string{ "Content-Type": "application/json", }, respStatus: http.StatusMethodNotAllowed, }, } { mux := runtime.NewServeMux() for _, p := range spec.patterns { func(p stubPattern) { pat, err := runtime.NewPattern(1, p.ops, p.pool, "") if err != nil { t.Fatalf("runtime.NewPattern(1, %#v, %#v, %q) failed with %v; want success", p.ops, p.pool, "", err) } mux.Handle(p.method, pat, func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) { fmt.Fprintf(w, "%s %s", p.method, pat.String()) }) }(p) } url := fmt.Sprintf("http://host.example%s", spec.reqPath) r, err := http.NewRequest(spec.reqMethod, url, bytes.NewReader(nil)) if err != nil { t.Fatalf("http.NewRequest(%q, %q, nil) failed with %v; want success", spec.reqMethod, url, err) } for name, value := range spec.headers { r.Header.Set(name, value) } w := httptest.NewRecorder() mux.ServeHTTP(w, r) if got, want := w.Code, spec.respStatus; got != want { t.Errorf("w.Code = %d; want %d; patterns=%v; req=%v", got, want, spec.patterns, r) } if spec.respContent != "" { if got, want := w.Body.String(), spec.respContent; got != want { t.Errorf("w.Body = %q; want %q; patterns=%v; req=%v", got, want, spec.patterns, r) } } } }
func (s *server) Serve() (retErr error) { var listener net.Listener var spec string var err error var addr string switch s.protocol { case protocolTCP: listener, spec, err = newTCPListener(s.driverName, s.groupOrAddress) addr = s.groupOrAddress case protocolUnix: listener, spec, err = newUnixListener(s.driverName, s.groupOrAddress) addr = s.driverName default: return fmt.Errorf("unknown protocol: %d", s.protocol) } if err != nil { return err } grpcPort := s.opts.GRPCPort if grpcPort == 0 { grpcPort = DefaultGRPCPort } grpcServer := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint32)) RegisterAPIServer(grpcServer, s.apiServer) s.registerFunc(grpcServer) grpcListener, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort)) if err != nil { return err } grpcErrC := make(chan error) httpErrC := make(chan error) errCCount := 1 go func() { grpcErrC <- grpcServer.Serve(grpcListener) }() time.Sleep(1 * time.Second) ctx, cancel := context.WithCancel(context.Background()) mux := runtime.NewServeMux( runtime.WithForwardResponseOption( func(_ context.Context, responseWriter http.ResponseWriter, _ proto.Message) error { responseWriter.Header().Set("Content-Type", "application/vnd.docker.plugins.v1.1+json") return nil }, ), ) conn, err := grpc.Dial(fmt.Sprintf("0.0.0.0:%d", grpcPort), grpc.WithInsecure()) if err != nil { glog.Flush() cancel() return err } go func() { <-ctx.Done() _ = conn.Close() }() if err := RegisterAPIHandler(ctx, mux, conn); err != nil { _ = conn.Close() glog.Flush() cancel() return err } if err := s.httpRegisterFunc(ctx, mux, conn); err != nil { _ = conn.Close() glog.Flush() cancel() return err } httpServer := &http.Server{ Addr: addr, Handler: mux, } gracefulServer := &graceful.Server{ Timeout: 1 * time.Second, ShutdownInitiated: func() { glog.Flush() cancel() if spec != "" { _ = os.Remove(spec) } }, Server: httpServer, } errCCount++ go func() { httpErrC <- gracefulServer.Serve(listener) }() var errs []error grpcStopped := false for i := 0; i < errCCount; i++ { select { case grpcErr := <-grpcErrC: if grpcErr != nil { errs = append(errs, fmt.Errorf("grpc error: %s", grpcErr.Error())) } grpcStopped = true case httpErr := <-httpErrC: if httpErr != nil { errs = append(errs, fmt.Errorf("http error: %s", httpErr.Error())) } if !grpcStopped { grpcServer.Stop() _ = listener.Close() grpcStopped = true } } } if len(errs) > 0 { return fmt.Errorf("%v", errs) } return nil }
// Serve serves stuff. func Serve( port uint16, registerFunc func(*grpc.Server), opts ServeOptions, ) (retErr error) { start := time.Now() defer func() { if retErr != nil { protolog.Error( &ServerFinished{ Error: retErr.Error(), Duration: prototime.DurationToProto(time.Since(start)), }, ) } else { protolog.Info( &ServerFinished{ Duration: prototime.DurationToProto(time.Since(start)), }, ) } }() if port == 0 { return ErrMustSpecifyPort } if registerFunc == nil { return ErrMustSpecifyRegisterFunc } if opts.HTTPPort != 0 && opts.HTTPAddress != "" { return ErrCannotSpecifyBothHTTPPortAndHTTPAddress } s := grpc.NewServer(grpc.MaxConcurrentStreams(math.MaxUint32)) registerFunc(s) if opts.Version != nil { protoversion.RegisterAPIServer(s, protoversion.NewAPIServer(opts.Version)) } listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { return err } grpcErrC := make(chan error) grpcDebugErrC := make(chan error) httpErrC := make(chan error) errCCount := 1 go func() { grpcErrC <- s.Serve(listener) }() if opts.DebugPort != 0 { errCCount++ debugServer := &graceful.Server{ Timeout: 1 * time.Second, Server: &http.Server{ Addr: fmt.Sprintf(":%d", opts.DebugPort), Handler: http.DefaultServeMux, }, } go func() { grpcDebugErrC <- debugServer.ListenAndServe() }() } if (opts.HTTPPort != 0 || opts.HTTPAddress != "") && (opts.Version != nil || opts.HTTPRegisterFunc != nil) { time.Sleep(1 * time.Second) ctx, cancel := context.WithCancel(context.Background()) var mux *runtime.ServeMux if len(opts.ServeMuxOptions) == 0 { mux = runtime.NewServeMux() } else { mux = runtime.NewServeMux(opts.ServeMuxOptions...) } conn, err := grpc.Dial(fmt.Sprintf("0.0.0.0:%d", port), grpc.WithInsecure()) if err != nil { glog.Flush() cancel() return err } go func() { <-ctx.Done() _ = conn.Close() }() if opts.Version != nil { if err := protoversion.RegisterAPIHandler(ctx, mux, conn); err != nil { _ = conn.Close() glog.Flush() cancel() return err } } if opts.HTTPRegisterFunc != nil { if err := opts.HTTPRegisterFunc(ctx, mux, conn); err != nil { _ = conn.Close() glog.Flush() cancel() return err } } httpAddress := fmt.Sprintf(":%d", opts.HTTPPort) if opts.HTTPAddress != "" { httpAddress = opts.HTTPAddress } httpServer := &http.Server{ Addr: httpAddress, Handler: mux, } gracefulServer := &graceful.Server{ Timeout: 1 * time.Second, BeforeShutdown: opts.HTTPBeforeShutdown, ShutdownInitiated: func() { glog.Flush() cancel() if opts.HTTPShutdownInitiated != nil { opts.HTTPShutdownInitiated() } }, Server: httpServer, } if opts.HTTPStart != nil { close(opts.HTTPStart) } errCCount++ go func() { if opts.HTTPListener != nil { httpErrC <- gracefulServer.Serve(opts.HTTPListener) } else { httpErrC <- gracefulServer.ListenAndServe() } }() } protolog.Info( &ServerStarted{ Port: uint32(port), HttpPort: uint32(opts.HTTPPort), DebugPort: uint32(opts.DebugPort), HttpAddress: opts.HTTPAddress, }, ) var errs []error grpcStopped := false for i := 0; i < errCCount; i++ { select { case grpcErr := <-grpcErrC: if grpcErr != nil { errs = append(errs, fmt.Errorf("grpc error: %s", grpcErr.Error())) } grpcStopped = true case grpcDebugErr := <-grpcDebugErrC: if grpcDebugErr != nil { errs = append(errs, fmt.Errorf("grpc debug error: %s", grpcDebugErr.Error())) } if !grpcStopped { s.Stop() _ = listener.Close() grpcStopped = true } case httpErr := <-httpErrC: if httpErr != nil { errs = append(errs, fmt.Errorf("http error: %s", httpErr.Error())) } if !grpcStopped { s.Stop() _ = listener.Close() grpcStopped = true } } } if len(errs) > 0 { return fmt.Errorf("%v", errs) } return nil }
// Start starts the server on the specified port, starts gossip and // initializes the node using the engines from the server's context. func (s *Server) Start() error { tlsConfig, err := s.ctx.GetServerTLSConfig() if err != nil { return err } httpServer := netutil.MakeServer(s.stopper, tlsConfig, s) plainRedirectServer := netutil.MakeServer(s.stopper, tlsConfig, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // TODO(tamird): s/308/http.StatusPermanentRedirect/ when it exists. http.Redirect(w, r, "https://"+r.Host+r.RequestURI, 308) })) // The following code is a specialization of util/net.go's ListenAndServe // which adds pgwire support. A single port is used to serve all protocols // (pg, http, h2) via the following construction: // // non-TLS case: // net.Listen -> cmux.New // | // - -> pgwire.Match -> pgwire.Server.ServeConn // - -> cmux.Any -> grpc.(*Server).Serve // // TLS case: // net.Listen -> cmux.New // | // - -> pgwire.Match -> pgwire.Server.ServeConn // - -> cmux.Any -> grpc.(*Server).Serve // // Note that the difference between the TLS and non-TLS cases exists due to // Go's lack of an h2c (HTTP2 Clear Text) implementation. See inline comments // in util.ListenAndServe for an explanation of how h2c is implemented there // and here. ln, err := net.Listen("tcp", s.ctx.Addr) if err != nil { return err } unresolvedAddr, err := officialAddr(s.ctx.Addr, ln.Addr()) if err != nil { return err } s.ctx.Addr = unresolvedAddr.String() s.rpcContext.SetLocalInternalServer(s.node) s.stopper.RunWorker(func() { <-s.stopper.ShouldQuiesce() if err := ln.Close(); err != nil { log.Fatal(err) } }) m := cmux.New(ln) pgL := m.Match(pgwire.Match) anyL := m.Match(cmux.Any()) httpLn, err := net.Listen("tcp", s.ctx.HTTPAddr) if err != nil { return err } unresolvedHTTPAddr, err := officialAddr(s.ctx.HTTPAddr, httpLn.Addr()) if err != nil { return err } s.ctx.HTTPAddr = unresolvedHTTPAddr.String() s.stopper.RunWorker(func() { <-s.stopper.ShouldQuiesce() if err := httpLn.Close(); err != nil { log.Fatal(err) } }) if tlsConfig != nil { httpMux := cmux.New(httpLn) clearL := httpMux.Match(cmux.HTTP1()) tlsL := httpMux.Match(cmux.Any()) s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(httpMux.Serve()) }) s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(plainRedirectServer.Serve(clearL)) }) httpLn = tls.NewListener(tlsL, tlsConfig) } s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(httpServer.Serve(httpLn)) }) s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(s.grpc.Serve(anyL)) }) s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(httpServer.ServeWith(pgL, func(conn net.Conn) { if err := s.pgServer.ServeConn(conn); err != nil && !netutil.IsClosedConnection(err) { log.Error(err) } })) }) if len(s.ctx.SocketFile) != 0 { // Unix socket enabled: postgres protocol only. unixLn, err := net.Listen("unix", s.ctx.SocketFile) if err != nil { return err } s.stopper.RunWorker(func() { <-s.stopper.ShouldQuiesce() if err := unixLn.Close(); err != nil { log.Fatal(err) } }) s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(httpServer.ServeWith(unixLn, func(conn net.Conn) { if err := s.pgServer.ServeConn(conn); err != nil && !netutil.IsClosedConnection(err) { log.Error(err) } })) }) } s.gossip.Start(s.grpc, unresolvedAddr) if err := s.node.start(unresolvedAddr, s.ctx.Engines, s.ctx.NodeAttributes); err != nil { return err } // Begin recording runtime statistics. s.startSampleEnvironment(s.ctx.MetricsSampleInterval) // Begin recording time series data collected by the status monitor. s.tsDB.PollSource(s.recorder, s.ctx.MetricsSampleInterval, ts.Resolution10s, s.stopper) // Begin recording status summaries. s.node.startWriteSummaries(s.ctx.MetricsSampleInterval) s.sqlExecutor.SetNodeID(s.node.Descriptor.NodeID) // Create and start the schema change manager only after a NodeID // has been assigned. testingKnobs := new(sql.SchemaChangeManagerTestingKnobs) if s.ctx.TestingKnobs.SQLSchemaChangeManager != nil { testingKnobs = s.ctx.TestingKnobs.SQLSchemaChangeManager.(*sql.SchemaChangeManagerTestingKnobs) } sql.NewSchemaChangeManager(testingKnobs, *s.db, s.gossip, s.leaseMgr).Start(s.stopper) log.Infof("starting %s server at %s", s.ctx.HTTPRequestScheme(), unresolvedHTTPAddr) log.Infof("starting grpc/postgres server at %s", unresolvedAddr) if len(s.ctx.SocketFile) != 0 { log.Infof("starting postgres server at unix:%s", s.ctx.SocketFile) } s.stopper.RunWorker(func() { netutil.FatalIfUnexpected(m.Serve()) }) // Initialize grpc-gateway mux and context. jsonpb := &util.JSONPb{ EnumsAsInts: true, EmitDefaults: true, Indent: " ", } protopb := new(util.ProtoPb) gwMux := gwruntime.NewServeMux( gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, jsonpb), gwruntime.WithMarshalerOption(util.JSONContentType, jsonpb), gwruntime.WithMarshalerOption(util.AltJSONContentType, jsonpb), gwruntime.WithMarshalerOption(util.ProtoContentType, protopb), gwruntime.WithMarshalerOption(util.AltProtoContentType, protopb), ) gwCtx, gwCancel := context.WithCancel(context.Background()) s.stopper.AddCloser(stop.CloserFn(gwCancel)) // Setup HTTP<->gRPC handlers. var opts []grpc.DialOption if s.ctx.Insecure { opts = append(opts, grpc.WithInsecure()) } else { tlsConfig, err := s.ctx.GetClientTLSConfig() if err != nil { return err } opts = append( opts, // TODO(tamird): remove this timeout. It is currently necessary because // GRPC will not actually bail on a bad certificate error - it will just // retry indefinitely. See https://github.com/grpc/grpc-go/issues/622. grpc.WithTimeout(base.NetworkTimeout), grpc.WithBlock(), grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), ) } conn, err := s.rpcContext.GRPCDial(s.ctx.Addr, opts...) if err != nil { return errors.Errorf("error constructing grpc-gateway: %s; are your certificates valid?", err) } for _, gw := range []grpcGatewayServer{&s.admin, s.status, &s.tsServer} { if err := gw.RegisterGateway(gwCtx, gwMux, conn); err != nil { return err } } var uiFileSystem http.FileSystem uiDebug := envutil.EnvOrDefaultBool("debug_ui", false) if uiDebug { uiFileSystem = http.Dir("ui") } else { uiFileSystem = &assetfs.AssetFS{ Asset: ui.Asset, AssetDir: ui.AssetDir, AssetInfo: ui.AssetInfo, } } uiFileServer := http.FileServer(uiFileSystem) s.mux.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { if uiDebug { r.URL.Path = "debug.html" } else { r.URL.Path = "release.html" } } uiFileServer.ServeHTTP(w, r) })) // TODO(marc): when cookie-based authentication exists, // apply it for all web endpoints. s.mux.HandleFunc(debugEndpoint, http.HandlerFunc(handleDebug)) s.mux.Handle(adminEndpoint, gwMux) s.mux.Handle(ts.URLPrefix, gwMux) s.mux.Handle(statusPrefix, s.status) s.mux.Handle(healthEndpoint, s.status) if err := sdnotify.Ready(); err != nil { log.Errorf("failed to signal readiness using systemd protocol: %s", err) } return nil }
func TestMarshalerForRequest(t *testing.T) { r, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf(`http.NewRequest("GET", "http://example.com", nil) failed with %v; want success`, err) } r.Header.Set("Accept", "application/x-out") r.Header.Set("Content-Type", "application/x-in") mux := runtime.NewServeMux() in, out := runtime.MarshalerForRequest(mux, r) if _, ok := in.(*runtime.JSONPb); !ok { t.Errorf("in = %#v; want a runtime.JSONPb", in) } if _, ok := out.(*runtime.JSONPb); !ok { t.Errorf("out = %#v; want a runtime.JSONPb", in) } var marshalers [3]dummyMarshaler specs := []struct { opt runtime.ServeMuxOption wantIn runtime.Marshaler wantOut runtime.Marshaler }{ { opt: runtime.WithMarshalerOption(runtime.MIMEWildcard, &marshalers[0]), wantIn: &marshalers[0], wantOut: &marshalers[0], }, { opt: runtime.WithMarshalerOption("application/x-in", &marshalers[1]), wantIn: &marshalers[1], wantOut: &marshalers[0], }, { opt: runtime.WithMarshalerOption("application/x-out", &marshalers[2]), wantIn: &marshalers[1], wantOut: &marshalers[2], }, } for i, spec := range specs { var opts []runtime.ServeMuxOption for _, s := range specs[:i+1] { opts = append(opts, s.opt) } mux = runtime.NewServeMux(opts...) in, out = runtime.MarshalerForRequest(mux, r) if got, want := in, spec.wantIn; got != want { t.Errorf("in = %#v; want %#v", got, want) } if got, want := out, spec.wantOut; got != want { t.Errorf("out = %#v; want %#v", got, want) } } r.Header.Set("Content-Type", "application/x-another") in, out = runtime.MarshalerForRequest(mux, r) if got, want := in, &marshalers[1]; got != want { t.Errorf("in = %#v; want %#v", got, want) } if got, want := out, &marshalers[0]; got != want { t.Errorf("out = %#v; want %#v", got, want) } }