コード例 #1
0
ファイル: gorai.go プロジェクト: go51/gorai
func (g *gorai) Run() {
	if isConsole() {
		consoleHandler()
		return
	}

	cer, err := tls.LoadX509KeyPair(g.config.Framework.WebServerSSL.CtrFile, g.config.Framework.WebServerSSL.KeyFile)
	if err != nil {
		panic(err)
	}

	config := &tls.Config{Certificates: []tls.Certificate{cer}}

	server := &http.Server{
		Addr:         g.config.Framework.WebServer.Host + ":" + g.config.Framework.WebServer.Port,
		Handler:      webReWriteHandler(),
		ReadTimeout:  g.config.Framework.WebServer.ReadTimeout * time.Second,
		WriteTimeout: g.config.Framework.WebServer.WriteTimeout * time.Second,
	}
	serverSSL := &http.Server{
		Addr:         g.config.Framework.WebServerSSL.Host + ":" + g.config.Framework.WebServerSSL.Port,
		Handler:      webHandler(),
		ReadTimeout:  g.config.Framework.WebServerSSL.ReadTimeout * time.Second,
		WriteTimeout: g.config.Framework.WebServerSSL.WriteTimeout * time.Second,
		TLSConfig:    config,
	}

	gracehttp.Serve(server, serverSSL)
}
コード例 #2
0
ファイル: server.go プロジェクト: leoliuzcl/skizze
/*
Run ...
*/
func (srv *Server) Run() {
	conf := config.GetConfig()
	port := int(conf.Port)
	logger.Info.Println("Server up and running on port: " + strconv.Itoa(port))
	err := gracehttp.Serve(&http.Server{Addr: ":" + strconv.Itoa(port), Handler: srv})
	utils.PanicOnError(err)
}
コード例 #3
0
ファイル: main.go プロジェクト: BigRoom/vision
func main() {
	var err error
	sentry, err = raven.NewClient(*sentryDSN, nil)
	if err != nil {
		log.Println("No sentry:", err)
	}

	restrict.ReadCryptoKey(*crypto)

	models.Init(
		*dbUser,
		*dbPass,
		*dbService,
		*dbPort,
		*dbName,
	)

	go tunnel.NewRPCServer(messages, *rpcAddr, *rpcPort)
	go messageLoop()

	r := setupRouting()

	pool = setupZombies()

	log.Println(gracehttp.Serve(
		&http.Server{
			Addr:    *httpAddr + ":" + *httpPort,
			Handler: r,
		},
	))
}
コード例 #4
0
func ServeApi() {
	ApiServers := make([]*http.Server, len(utils.Cfg.ServerSettings.Ports))
	for i, port := range utils.Cfg.ServerSettings.Ports {
		ApiServers[i] = newApiServer(port)
	}
	gracehttp.Serve(ApiServers...)
}
コード例 #5
0
ファイル: main.go プロジェクト: shuhaowu/towncrier
func main() {
	wg := &sync.WaitGroup{}

	notificationBackend := backend.GetBackend(applicationConfig.BackendName)
	err := notificationBackend.Initialize(applicationConfig.BackendOpenString)
	if err != nil {
		logger.WithField("error", err).Panic("cannot initialize backend")
	}

	notificationBackend.Start(wg)
	defer func() {
		notificationBackend.Shutdown()
		wg.Wait()
	}()

	notificationBackend.BlockUntilReady()
	receiverApp := webreceiver.NewApp(notificationBackend, applicationConfig.Receiver)

	receiverServer := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", applicationConfig.Receiver.ListenHost, applicationConfig.Receiver.ListenPort),
		Handler: receiverApp,
	}

	gracehttp.Serve(receiverServer)
}
コード例 #6
0
ファイル: server.go プロジェクト: itang/gomonkey
func main() {
	//runtime.GOMAXPROCS(runtime.NumCPU())
	e := echo.New()

	e.Use(mw.Logger())
	e.Use(mw.Recover())
	e.Use(mw.Gzip())

	e.Get("/", welcome)
	e.Get("/ping", ping)

	//// Start server
	//e.Run(":1323")

	// Get the http.Server
	s := e.Server(":8000")

	// HTTP2 is currently enabled by default in echo.New(). To override TLS handshake errors
	// you will need to override the TLSConfig for the server so it does not attempt to validate
	// the connection using TLS as required by HTTP2
	s.TLSConfig = nil

	// Serve it like a boss
	log.Fatal(gracehttp.Serve(s))
}
コード例 #7
0
ファイル: portfolio_server.go プロジェクト: bborbe/portfolio
func do() error {
	server, err := createServer()
	if err != nil {
		return err
	}
	glog.V(2).Infof("start server")
	return gracehttp.Serve(server)
}
コード例 #8
0
ファイル: stats_server.go プロジェクト: zhanglong2005/stats
func do(writer io.Writer, address string, documentRoot string, dbPath string) error {
	dbPath, err := io_util.NormalizePath(dbPath)
	if err != nil {
		return err
	}
	gracehttp.Serve(createServer(address, documentRoot, dbPath))
	return nil
}
コード例 #9
0
ファイル: demo.go プロジェクト: raceli/grace
func main() {
	flag.Parse()
	gracehttp.Serve(
		&http.Server{Addr: *address0, Handler: newHandler("Zero  ")},
		&http.Server{Addr: *address1, Handler: newHandler("First ")},
		&http.Server{Addr: *address2, Handler: newHandler("Second")},
	)
}
コード例 #10
0
ファイル: server.go プロジェクト: AlekSi/echo
func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Six sick bricks tick")
	})
	std := standard.New(":1323")
	std.SetHandler(e)
	gracehttp.Serve(std.Server)
}
コード例 #11
0
ファイル: main.go プロジェクト: maruel/git-scan
func mainImpl() error {
	port := flag.Int("port", 8010, "port number")
	notLocal := flag.Bool("all", false, "listen on all IPs, not just localhost")
	cwd, _ := os.Getwd()
	root := flag.String("root", filepath.Join(cwd, "repos"), "checkout root dir")
	flag.Parse()
	log.SetFlags(log.Ldate | log.Lmicroseconds | log.LUTC)

	if err := os.MkdirAll(*root, 0700); err != nil {
		return err
	}

	footer := ""
	if c := loadConfig(); c != nil {
		b := &bytes.Buffer{}
		if err := footerTmpl.Execute(b, c); err != nil {
			return err
		}
		footer = b.String()
	}
	repos := &repositories{
		root:   *root,
		delay:  60 * time.Second,
		repos:  map[string]*git{},
		footer: footer,
	}

	// TODO(maruel): This is a race condition with the parent process.
	if err := repos.init(); err != nil {
		return err
	}

	var addr string
	if *notLocal {
		addr = fmt.Sprintf(":%d", *port)
	} else {
		addr = fmt.Sprintf("localhost:%d", *port)
	}

	mux := http.NewServeMux()
	mux.Handle("/favicon.ico", restrictFunc(func(w http.ResponseWriter, r *http.Request) {
		// TODO(maruel): Eh.
		http.Redirect(w, r, "https://git-scm.com/images/logos/downloads/Git-Icon-1788C.png", http.StatusFound)
	}, "GET"))
	mux.Handle("/", repos)

	s := &http.Server{
		Addr:    addr,
		Handler: exitOnPanic{&loggingHandler{mux, nil}},
	}

	// TODO(maruel): Handle Ctrl-C to quick shutdown but wait for git operations.
	err := gracehttp.Serve(s)
	interrupt.Set()
	repos.wg.Wait()
	return err
}
コード例 #12
0
ファイル: server.go プロジェクト: Attamusc/QueueBert
func main() {
	// Setup
	e := echo.New()
	e.Get("/", func(c *echo.Context) error {
		return c.String(http.StatusOK, "Six sick bricks tick")
	})

	gracehttp.Serve(e.Server(":1323"))
}
コード例 #13
0
ファイル: main.go プロジェクト: Arata3/proxystaticfile
func main() {
	http.HandleFunc("/", findFile)
	log.Println("[server]:start :", conf.Port)
	log.Println(conf)
	err := gracehttp.Serve(&http.Server{Addr: ":" + conf.Port, Handler: nil})
	// err := http.ListenAndServe(":"+conf.Port, nil)
	if err != nil {
		log.Fatal(err)
	}

}
コード例 #14
0
ファイル: demo.go プロジェクト: coreroller/coreroller
func main() {
	flag.Parse()

	go checkForUpdates()

	gracehttp.Serve(
		&http.Server{Addr: ":8111", Handler: newHandler("handler1")},
		&http.Server{Addr: ":8112", Handler: newHandler("handler2")},
		&http.Server{Addr: ":8113", Handler: newHandler("handler3")},
	)
}
コード例 #15
0
ファイル: app.go プロジェクト: yudppp/go-simple-server
func main() {
	options := Options{
		Port: 8080,
	}
	config.MustResolve(&options)

	port := options.Port
	s := &http.Server{
		Addr:    fmt.Sprintf(":%v", port),
		Handler: newHandler(),
	}
	gracehttp.Serve(s)
}
コード例 #16
0
ファイル: main.go プロジェクト: daizong/go-web-starter-kit
func startServer(app *app.App) error {
	addr := fmt.Sprintf(":%d", config.Port)
	server := &http.Server{
		Addr:         addr,
		Handler:      app,
		ReadTimeout:  time.Second * 10,
		WriteTimeout: time.Second * 10,
	}
	server.SetKeepAlivesEnabled(false)

	logger.Infof("listen on: %s", addr)
	return gracehttp.Serve(server)
}
コード例 #17
0
func main() {
	port = flag.String("port", ":8080", "port for this HTTP server to listen on")
	target = flag.String("target", "https://www.marksandspencer.com", "target URL for reverse proxy")
	flag.Parse()

	u, err := url.Parse(*target)
	if err != nil {
		log.Fatal(err)
	}

	proxy := newReverseProxy(u)
	log.Fatal(gracehttp.Serve(
		&http.Server{Addr: *port, Handler: proxy},
	))
}
コード例 #18
0
ファイル: ee.go プロジェクト: ytake/echo-extended
func main() {
	// Echo instance
	e := echo.New()
	applicationConfig := foundation.NewApplicationConfig()
	handler := foundation.ApplicationLogFile()
	foundation.RegisterFileLogger(e, handler)
	// register global middleware
	middleware.GlobalMiddleware(e)
	// register application routes
	foundation.ApplicationRoutes(e)
	defer handler.FileHandler.Close()
	// boot application server
	standard := standard.New(fmt.Sprintf("%s:%s", *applicationConfig.Host, *applicationConfig.Port))
	standard.SetHandler(e)
	gracehttp.Serve(standard.Server)
}
コード例 #19
0
ファイル: server.go プロジェクト: train860/picfit
func Run(path string) error {
	runtime.GOMAXPROCS(runtime.NumCPU())

	app, err := NewFromConfigPath(path)

	if err != nil {
		return err
	}

	n := app.InitRouter()

	server := &http.Server{Addr: fmt.Sprintf(":%s", strconv.Itoa(app.Port())), Handler: n}

	gracehttp.Serve(server)

	return nil
}
コード例 #20
0
ファイル: main.go プロジェクト: TeamTrumpet/waltz
func main() {
	// fetch config from environment
	awsRegion := os.Getenv("AWS_REGION")
	awsBucketName := os.Getenv("AWS_BUCKET")
	awsBucketPrefix := os.Getenv("AWS_BUCKET_PREFIX")

	// create the s3 client
	client := s3.New(nil)

	// create middleware
	n := negroni.Classic()

	// create mux
	mux := http.NewServeMux()

	resizePath := fmt.Sprintf("/%s/", awsBucketPrefix)

	ro := resizeOpts{
		bucket: awsBucketName,
		prefix: awsBucketPrefix,
		path:   resizePath,
		region: awsRegion,
		client: client,
	}

	resizeHandler := newResizeHandler(ro)

	log.Println("Serving images from", resizePath)

	mux.HandleFunc(resizePath, resizeHandler)
	mux.HandleFunc("/robots.txt", robotsHandler)

	// add mux to middleware stack
	n.UseHandler(mux)

	server := &http.Server{
		Addr:    fmt.Sprintf("0.0.0.0:%s", os.Getenv("PORT")),
		Handler: n,
	}

	log.Printf("Starting server on 0.0.0.0:%s\n", os.Getenv("PORT"))

	// run using gracehttp
	gracehttp.Serve(server)
}
コード例 #21
0
ファイル: main.go プロジェクト: eirka/eirka-admin
func main() {
	r := gin.Default()

	r.Use(cors.CORS())
	// verified the csrf token from the request
	r.Use(csrf.Verify())

	r.GET("/status", status.StatusController)
	r.NoRoute(c.ErrorController)

	// requires mod perms
	admin := r.Group("/")

	admin.Use(validate.ValidateParams())
	admin.Use(user.Auth(true))
	admin.Use(user.Protect())

	admin.GET("/statistics/:ib", c.StatisticsController)
	admin.GET("/log/board/:ib/:page", c.BoardLogController)
	admin.GET("/log/mod/:ib/:page", c.ModLogController)

	admin.DELETE("/tag/:ib/:id", c.DeleteTagController)
	admin.DELETE("/imagetag/:ib/:image/:tag", c.DeleteImageTagController)
	admin.DELETE("/thread/:ib/:id", c.DeleteThreadController)
	admin.DELETE("/post/:ib/:thread/:id", c.DeletePostController)

	admin.POST("/tag/:ib", c.UpdateTagController)
	admin.POST("/sticky/:ib/:thread", c.StickyThreadController)
	admin.POST("/close/:ib/:thread", c.CloseThreadController)
	admin.POST("/ban/ip/:ib/:thread/:post", c.BanIPController)
	admin.POST("/ban/file/:ib/:thread/:post", c.BanFileController)
	admin.POST("/user/resetpassword/:ib", c.ResetPasswordController)

	//admin.DELETE("/thread/:id", c.PurgeThreadController)
	//admin.DELETE("/post/:thread/:id", c.PurgePostController)
	//admin.DELETE("/flushcache", c.DeleteCacheController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", local.Settings.Admin.Host, local.Settings.Admin.Port),
		Handler: r,
	}

	gracehttp.Serve(s)

}
コード例 #22
0
ファイル: server.go プロジェクト: jameswei/kingtask
func main() {
	// Setup
	e := echo.New()
	e.Get("/", func(c *echo.Context) error {
		return c.String(http.StatusOK, "Six sick bricks tick")
	})

	// Get the http.Server
	s := e.Server(":1323")

	// HTTP2 is currently enabled by default in echo.New(). To override TLS handshake errors
	// you will need to override the TLSConfig for the server so it does not attempt to valudate
	// the connection using TLS as required by HTTP2
	s.TLSConfig = nil

	// Serve it like a boss
	gracehttp.Serve(s)
}
コード例 #23
0
ファイル: main.go プロジェクト: jdef/oinker-go
func main() {
	flagSet := flag.CommandLine
	flags := parseFlags(flagSet)
	log.Printf("Flags: %+v", flags)

	oinker := &Oinker{}

	if *flags.cassandraAddr != "" {
		oinker.CQLHosts = []string{*flags.cassandraAddr}
	} else if *flags.cassandraSRV != "" && *flags.cassandraDNS == "" || *flags.cassandraSRV == "" && *flags.cassandraDNS != "" {
		log.Fatalf("Invalid input: cassandra-srv and cassandra-dns must both be specified to enable cassandra usage")
	} else if *flags.cassandraSRV != "" && *flags.cassandraDNS != "" {
		hosts, err := lookupCassandraHosts(*flags.cassandraSRV, *flags.cassandraDNS)
		if err != nil {
			log.Fatalf("Error looking up Cassandra SRV records: %s", err)
		}
		oinker.CQLHosts = hosts
	}

	graph := oinker.NewGraph()

	var oinkRepo model.OinkRepo
	inject.ExtractAssignable(graph, &oinkRepo)
	err := oinkRepo.Init()
	if err != nil {
		log.Fatalf("Error Initializing Repo: %s", err)
	}

	var mux controller.MuxServer
	inject.ExtractAssignable(graph, &mux)

	var controllers []controller.Controller
	inject.FindAssignable(graph, &controllers)
	for _, c := range controllers {
		log.Println("Registering controller:", c.Name())
		c.RegisterHandlers(mux)
	}

	// serve and listen for shutdown signals
	gracehttp.Serve(
		&http.Server{Addr: *flags.address, Handler: mux},
	)
}
コード例 #24
0
ファイル: testserver.go プロジェクト: train860/picfit
func main() {
	var httpAddr, httpsAddr string
	flag.StringVar(&httpAddr, "http", ":48560", "http address to bind to")
	flag.StringVar(&httpsAddr, "https", ":48561", "https address to bind to")
	flag.Parse()

	// we have self signed certs
	http.DefaultTransport = &http.Transport{
		DisableKeepAlives: true,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}

	err := flag.Set("gracehttp.log", "false")
	if err != nil {
		log.Fatalf("Error setting gracehttp.log: %s", err)
	}

	// print json to stderr once we can successfully connect to all three
	// addresses. the ensures we only print the line once we're ready to serve.
	go func() {
		var wg sync.WaitGroup
		wg.Add(2)
		go wait(&wg, fmt.Sprintf("http://%s/sleep/?duration=1ms", httpAddr))
		go wait(&wg, fmt.Sprintf("https://%s/sleep/?duration=1ms", httpsAddr))
		wg.Wait()

		err = json.NewEncoder(os.Stderr).Encode(&response{Pid: os.Getpid()})
		if err != nil {
			log.Fatalf("Error writing startup json: %s", err)
		}
	}()

	err = gracehttp.Serve(
		&http.Server{Addr: httpAddr, Handler: newHandler()},
		httpsServer(httpsAddr),
	)
	if err != nil {
		log.Fatalf("Error in gracehttp.Serve: %s", err)
	}
}
コード例 #25
0
ファイル: main.go プロジェクト: moomou/maingo
func main() {
	if serviceConfigPath == "" {
		serviceConfigPath = DEFAULT_CONFIG_PATH
	}
	if serverPort == ":" {
		serverPort = "localhost:9990"
	}

	sc, err := ParseServiceConfig(&serviceConfigPath)

	if err != nil {
		panic(err)
	}

	handler := RegisterServices(sc)

	fmt.Printf("Starting server on %s...\n", serverPort)

	gracehttp.Serve(
		&http.Server{Addr: serverPort, Handler: handler},
	)
}
コード例 #26
0
ファイル: main.go プロジェクト: mesosphere/oinker-go
func main() {
	flagSet := flag.CommandLine
	flags := parseFlags(flagSet)
	log.Infof("Flags: %+v", flags)

	oinker := &Oinker{}

	if *flags.cassandraAddr != "" {
		oinker.CQLHosts = []string{*flags.cassandraAddr}
		oinker.CQLReplicationFactor = *flags.cassandraRepl
	}

	graph := oinker.NewGraph()
	defer graph.Finalize()

	// initialize cassandra (connection, keyspace, tables)
	var oinkRepo service.OinkRepo
	inject.ExtractAssignable(graph, &oinkRepo)
	svc, ok := oinkRepo.(inject.Initializable)
	if ok {
		svc.Initialize()
	}

	var mux controller.MuxServer
	inject.ExtractAssignable(graph, &mux)

	var controllers []controller.Controller
	inject.FindAssignable(graph, &controllers)
	for _, c := range controllers {
		log.Infof("Registering controller:", c.Name())
		c.RegisterHandlers(mux)
	}

	// serve and listen for shutdown signals
	gracehttp.Serve(
		&http.Server{Addr: *flags.address, Handler: mux},
	)
}
コード例 #27
0
func main() {
	fmt.Println("Starting web server")

	// Set routes
	router := httprouter.New()
	router.HandleMethodNotAllowed = false
	router.POST("/upload", upload)
	router.NotFound = emptypage

	s := &http.Server{
		Addr:           bind,
		Handler:        router,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1024 * 6, // 4k cookie + 2k http request
	}

	s.SetKeepAlivesEnabled(true)

	if err := gracehttp.Serve(s); err != nil {
		panic(err)
	}
}
コード例 #28
0
func main() {
	bind := flag.String("bind", "0.0.0.0:5241", "Bind to this IP:port combination")
	flag.Parse()

	// Set routes
	router := httprouter.New()
	router.HandleMethodNotAllowed = false
	router.POST("/upload", upload)
	router.NotFound = notFound{}

	s := &http.Server{
		Addr:           *bind,
		Handler:        router,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1024 * 6, // 4k cookie + 2k http request
	}

	s.SetKeepAlivesEnabled(true)

	if err := gracehttp.Serve(s); err != nil {
		panic(err)
	}
}
コード例 #29
0
ファイル: server.go プロジェクト: techjanitor/fluorescences
// start will initialize the gin server
func start(name, address string, port int) {

	// init store
	u.Initialize(name)

	// create pid file
	pidfile.SetPidfilePath(fmt.Sprintf("/run/fluorescences/%s.pid", name))

	err := pidfile.Write()
	if err != nil {
		panic("Could not write pid file")
	}

	// load the site templates
	t := template.Must(template.New("public").Funcs(u.TemplateFuncs).ParseGlob("templates/*.tmpl"))

	r := gin.Default()

	// load template into gin
	r.SetHTMLTemplate(t)

	// serve our static files
	r.Static("/css", "./css")
	r.Static("/images", "./images")
	r.StaticFile("/logo.png", "./logo.png")

	// if nothing matches
	r.NoRoute(c.ErrorController)

	// routing group for public handlers
	public := r.Group("/")

	public.GET("/", blog.ViewController)
	public.GET("/blog/:page", blog.ViewController)
	public.GET("/categories", category.IndexController)
	public.GET("/comics/:id/:page", gallery.IndexController)
	public.GET("/comic/:id/:page", m.Private(), gallery.ViewController)
	public.GET("/image/:id/:page", m.Private(), image.ViewController)
	public.GET("/gallery/key/:id", keys.InputController)
	public.GET("/commission", com.ViewController)

	// routing group for admin handlers
	authed := r.Group("/admin")
	// add a CSRF cookie and session token to requests
	authed.Use(csrf.Cookie())

	authed.GET("/login", admin.LoginController)
	authed.POST("/login", admin.AuthController)
	authed.GET("/logout", admin.LogoutController)

	// ensure the user is authenticated
	authed.Use(m.Auth())

	authed.GET("/panel", admin.PanelController)

	authed.GET("/blog", blog.NewController)
	authed.GET("/blog/edit/:id", blog.EditController)

	authed.GET("/link/edit/:id", link.EditController)

	authed.GET("/category", category.NewController)
	authed.GET("/category/edit/:id", category.EditController)

	authed.GET("/gallery", gallery.NewController)
	authed.GET("/gallery/edit/:id", gallery.EditController)

	authed.GET("/image/edit/:gallery/:image", image.EditController)

	// authenticates the CSRF session token
	authed.Use(csrf.Verify())

	authed.POST("/settings/update", admin.UpdateController)

	authed.POST("/blog/new", blog.PostController)
	authed.POST("/blog/delete", blog.DeleteController)
	authed.POST("/blog/update", blog.UpdateController)

	authed.POST("/link/new", link.NewController)
	authed.POST("/link/delete", link.DeleteController)
	authed.POST("/link/update", link.UpdateController)

	authed.POST("/category/new", category.PostController)
	authed.POST("/category/delete", category.DeleteController)
	authed.POST("/category/update", category.UpdateController)

	authed.POST("/gallery/new", gallery.PostController)
	authed.POST("/gallery/delete", gallery.DeleteController)
	authed.POST("/gallery/update", gallery.UpdateController)
	authed.POST("/gallery/private", gallery.PrivateController)
	authed.POST("/gallery/image/new", image.NewController)
	authed.POST("/gallery/image/delete", image.DeleteController)
	authed.POST("/gallery/image/update", image.UpdateController)
	authed.POST("/gallery/key/new", keys.NewController)
	authed.POST("/gallery/key/delete", keys.DeleteController)

	authed.POST("/commission/update", com.UpdateController)

	authed.POST("/password/update", admin.PasswordController)

	s := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", address, port),
		Handler: r,
	}

	gracehttp.Serve(s)

}
コード例 #30
0
ファイル: app.go プロジェクト: na--/nedomi
// Uses our own listener to make our server stoppable. Similar to
// net.http.Server.ListenAndServer only this version saves a reference to the listener
func (a *Application) listenAndServe() error {
	// Serve accepts incoming connections on the Listener lsn, creating a
	// new service goroutine for each.  The service goroutines read requests and
	// then call the handler (i.e. ServeHTTP() ) to reply to them.
	return gracehttp.Serve(a.httpSrv)
}