Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
The frontend runs a service to serve user-facing traffic.
package main

import (
	
	
	
	
	

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
)

var (
	queueName      = config.GetEnv("GO_DISCOVERY_FRONTEND_TASK_QUEUE", "")
	workers        = flag.Int("workers", 10, "number of concurrent requests to the fetch service, when running locally")
	_              = flag.String("static", "content/static", "path to folder containing static files served")
	thirdPartyPath = flag.String("third_party", "third_party", "path to folder containing third-party libraries")
	devMode        = flag.Bool("dev", false, "enable developer mode (reload templates on each page load, serve non-minified JS/CSS, etc.)")
	disableCSP     = flag.Bool("nocsp", false, "disable Content Security Policy")
	proxyURL       = flag.String("proxy_url", "https://proxy.golang.org", "Uses the module proxy referred to by this URL "+
		"for direct proxy mode and frontend fetches")
	directProxy = flag.Bool("direct_proxy", false, "if set to true, uses the module proxy referred to by this URL "+
		"as a direct backend, bypassing the database")
	bypassLicenseCheck = flag.Bool("bypass_license_check", false, "display all information, even for non-redistributable paths")
	hostAddr           = flag.String("host", "localhost:8080", "Host address for the server")
)

func () {
	flag.Parse()
	 := context.Background()
	,  := config.Init()
	if  != nil {
		log.Fatal(, )
	}
	.Dump(os.Stderr)
	if .UseProfiler {
		if  := profiler.Start(profiler.Config{});  != nil {
			log.Fatalf(, "profiler.Start: %v", )
		}
	}

	log.SetLevel(.LogLevel)

	var (
		        func(context.Context) internal.DataSource
		 queue.Queue
	)
	if *bypassLicenseCheck {
		log.Info(, "BYPASSING LICENSE CHECKING: DISPLAYING NON-REDISTRIBUTABLE INFORMATION")
	}

	log.Infof(, "cmd/frontend: initializing cmdconfig.ExperimentGetter")
	 := cmdconfig.ExperimentGetter(, )
	log.Infof(, "cmd/frontend: initialized cmdconfig.ExperimentGetter")

	,  := proxy.New(*proxyURL)
	if  != nil {
		log.Fatal(, )
	}

	if *directProxy {
		var  *proxydatasource.DataSource
		if *bypassLicenseCheck {
			 = proxydatasource.NewBypassingLicenseCheck()
		} else {
			 = proxydatasource.New()
		}
		 = func(context.Context) internal.DataSource { return  }
	} else {
		,  := cmdconfig.OpenDB(, , *bypassLicenseCheck)
		if  != nil {
			log.Fatalf(, "%v", )
		}
		defer .Close()
		 = func(context.Context) internal.DataSource { return  }
The closure passed to queue.New is only used for testing and local execution, not in production. So it's okay that it doesn't use a per-request connection.
		,  = queue.New(, , queueName, *workers, ,
			func( context.Context, ,  string) (int, error) {
				return frontend.FetchAndUpdateState(, , , , , )
			})
		if  != nil {
			log.Fatalf(, "queue.New: %v", )
		}
	}

	var  *redis.Client
	if .RedisHAHost != "" {
		 = redis.NewClient(&redis.Options{
			Addr: .RedisHAHost + ":" + .RedisHAPort,
		})
	}
	 := cmdconfig.ReportingClient(, )
	,  := frontend.NewServer(frontend.ServerConfig{
		DataSourceGetter:     ,
		Queue:                ,
		CompletionClient:     ,
		TaskIDChangeInterval: config.TaskIDChangeIntervalFrontend,
		StaticPath:           template.TrustedSourceFromFlag(flag.Lookup("static").Value),
		ThirdPartyPath:       *thirdPartyPath,
		DevMode:              *devMode,
		AppVersionLabel:      .AppVersionLabel(),
		GoogleTagManagerID:   .GoogleTagManagerID,
		ServeStats:           .ServeStats,
		ReportingClient:      ,
	})
	if  != nil {
		log.Fatalf(, "frontend.NewServer: %v", )
	}

	 := dcensus.NewRouter(frontend.TagRoute)
	var  *redis.Client
	if .RedisCacheHost != "" {
		 = redis.NewClient(&redis.Options{
			Addr: .RedisCacheHost + ":" + .RedisCachePort,
		})
	}
	.Install(.Handle, , .AuthValues)
	 := append(dcensus.ServerViews,
		postgres.SearchLatencyDistribution,
		postgres.SearchResponseCount,
		frontend.FetchLatencyDistribution,
		frontend.FetchResponseCount,
		frontend.VersionTypeCount,
		middleware.CacheResultCount,
		middleware.CacheErrorCount,
		middleware.CacheLatency,
		middleware.QuotaResultCount,
	)
	if  := dcensus.Init(, ...);  != nil {
		log.Fatal(, )
We are not currently forwarding any ports on AppEngine, so serving debug information is broken.
	if !.OnAppEngine() {
		,  := dcensus.NewServer()
		if  != nil {
			log.Fatal(, )
		}
		go http.ListenAndServe(.DebugAddr("localhost:8081"), )
	}
	,  := .PanicHandler()
	if  != nil {
		log.Fatal(, )
	}
	log.Infof(, "cmd/frontend: initializing cmdconfig.Experimenter")
	 := cmdconfig.Experimenter(, , , )
	log.Infof(, "cmd/frontend: initialized cmdconfig.Experimenter")

	 := middleware.Identity()
	if  != nil {
		 = middleware.ErrorReporting(.Report)
	}
	 := middleware.Chain(
		middleware.RequestLog(cmdconfig.Logger(, , "frontend-log")),
		middleware.AcceptRequests(http.MethodGet, http.MethodPost, http.MethodHead), // accept only GETs, POSTs and HEADs
		middleware.BetaPkgGoDevRedirect(),
		middleware.Quota(.Quota, ),
		middleware.SecureHeaders(!*disableCSP), // must come before any caching for nonces to work
		middleware.Experiment(),
		middleware.Panic(),
		,
		middleware.Timeout(54*time.Second),
	)
	 := .HostAddr(*hostAddr)
	log.Infof(, "Listening on addr %s", )
	log.Fatal(, http.ListenAndServe(, ()))