func registerHandlers() { timeoutMsg := `{"error": {"code": 503,"message": "Request timeout."}}` // GET: http://server/allrankings allRankings := http.TimeoutHandler(wrapHandlerFunc("GET", allRankingsEndpoint, http.HandlerFunc(allRankingsHandler)), time.Duration(timeoutSecs)*time.Second, timeoutMsg) // GET: http://server/rankings?servers=ip1,ip2,ipn rankings := http.TimeoutHandler(wrapHandlerFunc("GET", rankingsEndpoint, http.HandlerFunc(rankingsHandler)), time.Duration(timeoutSecs)*time.Second, timeoutMsg) // GET: http://server/rankedservers rankedServers := http.TimeoutHandler(wrapHandlerFunc("GET", rankedServersEndpoint, http.HandlerFunc(rankedServersHandler)), time.Duration(timeoutSecs)*time.Second, timeoutMsg) if useGzip { http.Handle(allRankingsEndpoint, GzipHandler(allRankings)) http.Handle(rankingsEndpoint, GzipHandler(rankings)) http.Handle(rankedServersEndpoint, GzipHandler(rankedServers)) } else { http.Handle(allRankingsEndpoint, allRankings) http.Handle(rankingsEndpoint, rankings) http.Handle(rankedServersEndpoint, rankedServers) } }
func startApp(port string) { // Load environment variables envVars := loadEnvVars() // Override with cloud foundry user provided service credentials if specified. loadUPSVars(&envVars) app, settings, err := controllers.InitApp(envVars) if err != nil { // Print the error. fmt.Println(err.Error()) // Terminate the program with a non-zero value number. // Need this for testing purposes. os.Exit(1) } if settings.PProfEnabled { pprof.InitPProfRouter(app) } if envVars.NewRelicLicense != "" { fmt.Println("starting monitoring...") startMonitoring(envVars.NewRelicLicense) } fmt.Println("starting app now...") // TODO add better timeout message. By default it will just say "Timeout" protect := csrf.Protect([]byte(envVars.SessionKey), csrf.Secure(settings.SecureCookies)) http.ListenAndServe(":"+port, protect( http.TimeoutHandler(context.ClearHandler(app), helpers.TimeoutConstant, ""), )) }
func Run(config *config.APIConfig, ctx *context.RouteContext, st *utils.Stopper) { defer st.End() // Do not run the API service if there is no config. if config == nil { log.Infof("main API service is disabled.") return } log.Infof("starting main API on port %d.", config.Port) tlsConfig, err := tlsClientConfig(config.CAFile) if err != nil { log.Fatalf("could not initialize client cert authentication: %s\n", err) } if tlsConfig != nil { log.Info("main API configured with client certificate authentication") } srv := &graceful.Server{ Timeout: 0, // Already handled by our TimeOut middleware NoSignalHandling: true, // We want to use our own Stopper Server: &http.Server{ Addr: ":" + strconv.Itoa(config.Port), TLSConfig: tlsConfig, Handler: http.TimeoutHandler(newAPIHandler(ctx), config.Timeout, timeoutResponse), }, } listenAndServeWithStopper(srv, st, config.CertFile, config.KeyFile) log.Info("main API stopped") }
func main() { mux := mux.NewRouter() mux.HandleFunc("/", rootHandler) muxWithMiddlewares := http.TimeoutHandler(mux, time.Second*39, "Timeout!") http.ListenAndServe(":18080", muxWithMiddlewares) }
// Timeout limits a request handler to run for max time of the duration // Timeout( 15 * time.Second ) will limit the request to run no longer tan 15 seconds // When the request times out, the request will send a 503 response func Timeout(duration time.Duration) Middleware { return func(next ContextHandler) ContextHandler { return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { h := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { next(ctx, rw, req) }) http.TimeoutHandler(h, duration, "Server request timeout").ServeHTTP(rw, req) } } }
//start server TODO: run server with goroutine func (s *HttpServer) Start() error { var err error if Logger == nil { Logger = log.New(os.Stdout, "gomvc", log.Ldate|log.Ltime) } Logger.Println("gomvc http server start") err = s.Config.Check() if err != nil { Logger.Fatalln("gomvc check config error:", err) return err } Logger.Println("gomvc http server config:") Logger.Println(s.Config) if s.Filters == nil || len(s.Filters) == 0 { Logger.Println("gomvc http server invalid http filters") return ErrInvalidFilters } mux := http.NewServeMux() if s.Config.EnableProfile { Logger.Println("handle http profile on /debug/pprof") mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) mux.Handle("/debug/pprof/heap", pprof.Handler("heap")) mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) } if s.Config.Timeout > 0 { http.TimeoutHandler(s, time.Duration(s.Config.Timeout)*time.Second, MsgServerTimeout) } else { mux.Handle("/", s) } l, err := net.Listen("tcp", s.Config.Address) if err != nil { Logger.Fatalln("gomvc http server listen error:", err) return err } //TODO: run server with go func(){...}() s.Listener = l err = http.Serve(s.Listener, mux) if err != nil { Logger.Fatalln("gomvc http server start error:", err) return err } return nil }
func Handler(w http.ResponseWriter, r *http.Request) { t := time.Now() log.Println(r.RequestURI) // ResponseWriter wrapper w.Header().Set("Server", "YAG") w.Header().Set("Content-Type", "application/json") rw := &RenderResponseWriter{w: w} // Handler composition http.TimeoutHandler(&RenderHandler{}, time.Duration(config.Cfg.Webserver.Timeout)*time.Second, http.StatusText(http.StatusRequestTimeout)).ServeHTTP(rw, r) log.Printf("[%v] in %v\n", rw.Code, time.Now().Sub(t)) }
func startApp(port string) { // Load environment variables envVars := loadEnvVars() app, _, err := controllers.InitApp(envVars) if err != nil { // Print the error. fmt.Println(err.Error()) // Terminate the program with a non-zero value number. // Need this for testing purposes. os.Exit(1) } // TODO add better timeout message. By default it will just say "Timeout" http.ListenAndServe(":"+port, http.TimeoutHandler(context.ClearHandler(app), time.Second*5, "")) }
func newRouter() *mux.Router { r := mux.NewRouter().StrictSlash(true) for _, ar := range apiRoutes { handler := http.TimeoutHandler(compressGzip(ar.handlerFunc, config.Config.WebConfig.CompressResponses), time.Duration(config.Config.WebConfig.APIWebTimeout)*time.Second, `{"error": {"code": 503,"message": "Request timeout."}}`) handler = logger.LogWebRequest(handler, ar.name) r.Methods(ar.method). MatcherFunc(pathQStrToLowerMatcherFunc(r, ar.path, ar.queryStrings, getRequiredQryStringCount(ar.queryStrings))). Name(ar.name). Handler(handler) } return r }
func main() { c := readConfig() var w io.Writer if c.LogFilePath == "" { w = os.Stdout } else { fp, err := os.OpenFile(c.LogFilePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) if err != nil { panic("file open error") } w = fp } g_log = loggerProc(w, 16) if c.Heartbeat { // ハートビートを有効化 heartbeat := &http.Server{ Addr: ":80", Handler: &heartbeatHandle{text: "やっはろー"}, ReadTimeout: time.Duration(c.ReadTimeoutSec) * time.Second, WriteTimeout: time.Duration(c.WriteTimeoutSec) * time.Second, MaxHeaderBytes: c.MaxHeaderBytes, } go heartbeat.ListenAndServe() } t := time.Duration(c.ProxyTimeoutSec) * time.Second myHandler := &SummaryHandle{ conf: c, timeout: t, f: createDialTimeout(t), lb: loadBalancing(c.BalanceList), sesCh: sesProc(), ipCh: cacheIP(time.Duration(c.IPCacheTimeSec)*time.Second, t), } server := &http.Server{ Addr: fmt.Sprintf("%s:%d", c.Addr, c.Port), Handler: http.TimeoutHandler(myHandler, time.Duration(c.ServerTimeoutSec)*time.Second, "timeout!!!"), ReadTimeout: time.Duration(c.ReadTimeoutSec) * time.Second, WriteTimeout: time.Duration(c.WriteTimeoutSec) * time.Second, MaxHeaderBytes: c.MaxHeaderBytes, } // サーバ起動 server.ListenAndServe() }
func main() { pflag.Parse() if maxStorage > 1*bytesize.EB { log.Fatalf("Specified a maximum storage size that would overflow int64!") } if maxSize > 1*bytesize.EB { log.Fatalf("Specified a maximum paste size that would overflow int64!") } loadTemplates() var handler httpHandler handler.stats = &storage.Stats{ MaxNumber: *maxNumber, MaxStorage: int64(maxStorage), } log.Printf("siteURL = %s", *siteURL) log.Printf("listen = %s", *listen) log.Printf("lifeTime = %s", *lifeTime) log.Printf("maxSize = %s", maxSize) log.Printf("maxNumber = %d", *maxNumber) log.Printf("maxStorage = %s", maxStorage) args := pflag.Args() if len(args) == 0 { args = []string{"fs"} } if err := handler.setupStore(*lifeTime, args[0], args[1:]); err != nil { log.Fatalf("Could not setup paste store: %v", err) } ticker := time.NewTicker(reportInterval) go func() { logStats(handler.stats) for range ticker.C { logStats(handler.stats) } }() var finalHandler http.Handler = handler if *timeout > 0 { finalHandler = http.TimeoutHandler(finalHandler, *timeout, "") } http.Handle("/", finalHandler) log.Println("Up and running!") log.Fatal(http.ListenAndServe(*listen, nil)) }
func RunFunc() { r := render.New() mux, store := InitServerMux(r) n := negroni.Classic() n.Use(negroni.HandlerFunc(CookieMiddleware(store))) n.Use(negroni.HandlerFunc(RecoveryErr())) timeourHandler := http.TimeoutHandler(context.ClearHandler(mux), time.Duration(3*time.Second), timeoutErrMessage) n.UseHandler(timeourHandler) //All the middlerware we used l := log.New(os.Stdout, "[negroni] ", 0) l.Printf("listening on :80") server := http.Server{Addr: ":80", Handler: n} server.SetKeepAlivesEnabled(true) go MainMonitor() InitSchoolDB() InitCourseMap() InitSchoolStructs() l.Fatal(server.ListenAndServe()) }
// initNegroni initializes Negroni with all the middleware and starts it. func initNegroni(routes Routes, config ServiceConfig) (*RestServiceInfo, error) { var err error // Create negroni negroni := negroni.New() // Add content-negotiation middleware. // This is an example of using a middleware. // This will modify the response header to the // negotiated content type, and can then be used as // ct := w.Header().Get("Content-Type") // where w is http.ResponseWriter negroni.Use(NewNegotiator()) // Unmarshal data from the content-type format // into a map negroni.Use(NewUnmarshaller()) pubKeyLocation := config.Common.Api.AuthPublic if pubKeyLocation != "" { log.Infof("Reading public key from %s", pubKeyLocation) config.Common.PublicKey, err = ioutil.ReadFile(pubKeyLocation) } if err != nil { return nil, err } // We use the public key of root server to check the token. authMiddleware := AuthMiddleware{PublicKey: config.Common.PublicKey} negroni.Use(authMiddleware) timeoutMillis := getTimeoutMillis(config.Common) var dur time.Duration var readWriteDur time.Duration timeoutStr := fmt.Sprintf("%dms", timeoutMillis) dur, _ = time.ParseDuration(timeoutStr) timeoutStr = fmt.Sprintf("%dms", timeoutMillis+ReadWriteTimeoutDelta) readWriteDur, _ = time.ParseDuration(timeoutStr) router := newRouter(routes) timeoutHandler := http.TimeoutHandler(router, dur, TimeoutMessage) negroni.UseHandler(timeoutHandler) hostPort := config.Common.Api.GetHostPort() svcInfo, err := RunNegroni(negroni, hostPort, readWriteDur) return svcInfo, err }
func main() { NotFollowRedirect = errors.New("Not Follow Redirect") client = &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { return NotFollowRedirect }, Timeout: timeout} server := http.NewServeMux() filter = GetFilter(rules) //状态信息 server.HandleFunc("/status", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "Number Of Goroutines: %d", runtime.NumGoroutine()) }) //Proxy server.HandleFunc("/", proxy) http.TimeoutHandler(server, timeout, "Timeout") panic(http.ListenAndServe(":3000", server)) }
func main() { flag.Parse() //mime.AddExtensionType(".js", "application/javascript; charset=utf-8"); mime.AddExtensionType(".js", "text/javascript; charset=utf-8") http.Handle("/error/404", http.NotFoundHandler()) http.Handle("/error/timeout", http.TimeoutHandler(&NeverHandler{}, timeout, "Timeout")) //http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("./")))) http.Handle("/", http.FileServer(http.Dir("./"))) srvname := *name displayname := srvname if displayname == "" { displayname = "localhost" } srvname = srvname + ":" + *port displayname = displayname + ":" + *port log.Println("Serving test webpage at http://" + displayname + "/tests.html") if err := http.ListenAndServe(srvname, nil); err != nil { log.Fatal("ListenAndServe: %v", err) } }
func Wrapper(r Request) http.Handler { handler := r.Handler var hHandler http.Handler hHandler = tigertonic.Marshaled(handler) hHandler = buildHandlerWithTimeTracking(hHandler, r) // every request should return under 30 secs, if not return 503 service // unavailable hHandler = http.TimeoutHandler(hHandler, timeoutDuration, timedOutMsg) // set rate limiting if the handler has one if r.Ratelimit != nil { hHandler = BuildHandlerWithRateLimit(hHandler, r.Ratelimit) } // create the final handler return cors.Build(hHandler) }
func httpListener(ListenHttpHost, BrowserHttpHost string) { l, err := net.Listen("tcp", ListenHttpHost) if err != nil { log.Error("%v", err) // Если это повторный запуск и он не из консоли, то открываем окно браузера, т.к. скорее всего юзер тыкнул по иконке if *utils.Console == 0 { openBrowser(BrowserHttpHost) } log.Error("%v", utils.ErrInfo(err)) panic(err) os.Exit(1) } go func() { err = http.Serve(NewBoundListener(100, l), http.TimeoutHandler(http.DefaultServeMux, time.Duration(600*time.Second), "Your request has timed out")) if err != nil { log.Error("Error listening: %v (%v)", err, ListenHttpHost) panic(err) //os.Exit(1) } }() }
func main() { ncpu := runtime.NumCPU() log.Println("Starting app with GOMAXPROCS = ", ncpu) runtime.GOMAXPROCS(ncpu) // Build the stack of handlers appHandlers := handlers.AppHandlers() panicHandler := panichandler.NewHandler(appHandlers) timeoutHandler := http.TimeoutHandler(panicHandler, 60*time.Second, "Request Timed Out") ooyalaHeaderHandler := ooheaders.NewHandler(timeoutHandler) logHandler := ooyalalog.NewHandler(ooyalaHeaderHandler, os.Stdout, []string{"/healthz"}) clearContextHandler := context.ClearHandler(logHandler) addr := fmt.Sprintf(":%d", config.Settings.HTTPPort) server := &http.Server{ Addr: addr, Handler: clearContextHandler, } log.Println("Now listening on " + addr) log.Fatalf(server.ListenAndServe().Error()) }
func RunHealth(config *config.APIConfig, ctx *context.RouteContext, st *utils.Stopper) { defer st.End() // Do not run the API service if there is no config. if config == nil { log.Infof("health API service is disabled.") return } log.Infof("starting health API on port %d.", config.HealthPort) srv := &graceful.Server{ Timeout: 10 * time.Second, // Interrupt health checks when stopping NoSignalHandling: true, // We want to use our own Stopper Server: &http.Server{ Addr: ":" + strconv.Itoa(config.HealthPort), Handler: http.TimeoutHandler(newHealthHandler(ctx), config.Timeout, timeoutResponse), }, } listenAndServeWithStopper(srv, st, "", "") log.Info("health API stopped") }
func init() { test.SetupEnvironment() testURLBase = fmt.Sprintf("http://:%d", config.Config.WebConfig.APIWebPort) db.InitDBs() // create dump server file err := util.CreateDirectory(constants.DumpDirectory) if err != nil { panic("Unable to create dump directory used in tests") } err = util.CreateByteFile(constants.TestServerDumpJSON, constants.DumpFileFullPath( config.Config.DebugConfig.ServerDumpFilename), true) if err != nil { panic(fmt.Sprintf("Test dump file creation error: %s", err)) } // launch server go func() { r := mux.NewRouter().StrictSlash(true) for _, ar := range apiRoutes { var handler http.Handler handler = compressGzip(ar.handlerFunc, config.Config.WebConfig.CompressResponses) r.Methods(ar.method). MatcherFunc(pathQStrToLowerMatcherFunc(r, ar.path, ar.queryStrings, getRequiredQryStringCount(ar.queryStrings))). Name(ar.name). Handler(http.TimeoutHandler(handler, time.Duration(config.Config.WebConfig.APIWebTimeout)*time.Second, `{"error":"Timeout"}`)) } err := http.ListenAndServe(fmt.Sprintf(":%d", config.Config.WebConfig.APIWebPort), r) if err != nil { panic("Unable to start web server") } }() }
func init() { r := mux.NewRouter() r.NewRoute(). Methods("POST"). Path("/api/login"). Handler(handleIdentity(http.HandlerFunc(api.HandleLogin))) r.NewRoute(). Methods("POST"). Path("/api/logout"). Handler(handleIdentity(http.HandlerFunc(api.HandleLogout))) r.NewRoute(). Methods("GET"). Path("/api/accounts"). Handler(handleIdentity(http.HandlerFunc(api.ServeAccountList))) r.NewRoute(). Methods("POST"). Path("/api/accounts"). Handler(handleIdentity(http.HandlerFunc(api.CreateAccount))) r.NewRoute(). Methods("POST"). Path("/api/accounts/import"). Handler(handleIdentity(http.HandlerFunc(api.ImportAccounts))) r.NewRoute(). Methods("GET"). Path("/api/accounts/me"). Handler(handleIdentity(http.HandlerFunc(api.ServeAccountMe))) r.NewRoute(). Methods("GET"). Path("/api/accounts/by_handle"). Handler(handleIdentity(http.HandlerFunc(api.ServeAccountByHandle))) r.NewRoute(). Methods("GET"). Path("/api/accounts/{id}"). Handler(handleIdentity(http.HandlerFunc(api.ServeAccount))) r.NewRoute(). Methods("PUT"). Path("/api/accounts/{id}"). Handler(handleIdentity(http.HandlerFunc(api.UpdateAccount))) r.NewRoute(). Methods("PATCH"). Path("/api/accounts/{id}"). Handler(handleIdentity(http.HandlerFunc(api.UpdateAccountPart))) r.NewRoute(). Methods("DELETE"). Path("/api/accounts/{id}"). Handler(handleIdentity(http.HandlerFunc(api.DeleteAccount))) r.NewRoute(). Methods("GET"). Path("/api/contests/1"). Handler(handleIdentity(http.HandlerFunc(api.ServeContest))) r.NewRoute(). Methods("PUT"). Path("/api/contests/1"). Handler(handleIdentity(http.HandlerFunc(api.UpdateContest))) r.NewRoute(). Methods("GET"). Path("/api/standings"). Handler(handleIdentity(http.HandlerFunc(api.ServeStandingList))) r.NewRoute(). Methods("GET"). Path("/api/clarifications"). Handler(handleIdentity(http.HandlerFunc(api.ServeClarificationList))) r.NewRoute(). Methods("POST"). Path("/api/clarifications"). Handler(handleIdentity(http.HandlerFunc(api.CreateClarification))) r.NewRoute(). Methods("GET"). Path("/api/clarifications/{id}"). Handler(handleIdentity(http.HandlerFunc(api.ServeClarification))) r.NewRoute(). Methods("PUT"). Path("/api/clarifications/{id}"). Handler(handleIdentity(http.HandlerFunc(api.UpdateClarification))) r.NewRoute(). Methods("DELETE"). Path("/api/clarifications/{id}"). Handler(handleIdentity(http.HandlerFunc(api.DeleteClarification))) r.NewRoute(). Methods("GET"). Path("/api/problems"). Handler(handleIdentity(http.HandlerFunc(api.ServeProblemList))) r.NewRoute(). Methods("POST"). Path("/api/problems"). Handler(handleIdentity(http.HandlerFunc(api.CreateProblem))) r.NewRoute(). Methods("GET"). Path("/api/problems/by_slug"). Handler(handleIdentity(http.HandlerFunc(api.ServeProblemBySlug))) r.NewRoute(). Methods("GET"). Path("/api/problems/{id}"). Handler(handleIdentity(http.HandlerFunc(api.ServeProblem))) r.NewRoute(). Methods("PUT"). Path("/api/problems/{id}"). Handler(handleIdentity(http.HandlerFunc(api.UpdateProblem))) r.NewRoute(). Methods("DELETE"). Path("/api/problems/{id}"). Handler(handleIdentity(http.HandlerFunc(api.DeleteProblem))) r.NewRoute(). Methods("GET"). Path("/api/problems/{id}/tests/{no}/answer"). Handler(handleIdentity(http.HandlerFunc(api.ServeProblemTestAnswer))) r.NewRoute(). Methods("GET"). Path("/api/submissions"). Handler(handleIdentity(http.HandlerFunc(api.ServeSubmissionList))) r.NewRoute(). Methods("POST"). Path("/api/submissions"). Handler(handleIdentity(http.HandlerFunc(api.CreateSubmission))) r.NewRoute(). Methods("GET"). Path("/api/submissions/{id}"). Handler(handleIdentity(http.HandlerFunc(api.ServeSubmission))) r.NewRoute(). Methods("PUT"). Path("/api/submissions/{id}"). Handler(handleIdentity(http.HandlerFunc(api.UpdateSubmission))) r.NewRoute(). Methods("GET"). Path("/api/submissions/{id}/source"). Handler(handleIdentity(http.HandlerFunc(api.ServeSubmissionSource))) r.NewRoute(). Methods("GET"). Path("/api/submissions/{id}/tests/{no}/output"). Handler(handleIdentity(http.HandlerFunc(api.ServeSubmissionTestOutput))) r.NewRoute(). Methods("POST"). Path("/api/submissions/{id}/reset"). Handler(handleIdentity(http.HandlerFunc(api.ResetSubmission))) r.NewRoute(). Methods("POST"). Path("/api/submissions/{id}/judge"). Handler(handleIdentity(http.HandlerFunc(api.JudgeSubmission))) r.NewRoute(). Methods("POST"). Path("/api/executions"). Handler(handleIdentity(http.HandlerFunc(api.CreateExecution))) r.NewRoute(). Methods("GET"). Path("/api/executions/{id}"). Handler(handleIdentity(http.HandlerFunc(api.ServeExecution))) r.NewRoute(). Methods("POST"). Path("/api/executions/{id}/apply"). Handler(handleIdentity(http.HandlerFunc(api.ApplyExecution))) r.NewRoute(). Methods("GET"). Path("/api/executions/{id}/tests/{no}/output"). Handler(handleIdentity(http.HandlerFunc(api.ServeExecutionTestOutput))) r.NewRoute(). Methods("GET"). Path("/api/activities"). Handler(handleIdentity(http.HandlerFunc(api.ServeActivityList))) r.NewRoute(). Methods("GET"). Path("/api/notifications"). Handler(handleIdentity(http.HandlerFunc(api.ServeNotificationList))) r.NewRoute(). Methods("GET"). PathPrefix("/api"). Handler(http.NotFoundHandler()) r.NewRoute(). Methods("GET"). PathPrefix("/assets"). Handler(http.StripPrefix("/assets", http.HandlerFunc(ui.ServeAsset))) r.NewRoute(). Methods("GET"). PathPrefix("/"). Handler(handleIdentity(http.HandlerFunc(ui.ServeIndex))) http.Handle("/hub", handlePanic(handleIdentity(http.HandlerFunc(hub.HandleConnect)))) http.Handle("/", handlePanic(http.TimeoutHandler(handlers.CompressHandler(r), 8*time.Second, ""))) }
func timeoutHandler(h http.Handler) http.Handler { return http.TimeoutHandler(h, Configuration.HandlerTimeout, "request processing timed out") }
// Timeout uses the next layer of the middleware stack as the http.Handler // parameter of http.TimeoutHandler. func Timeout(dt time.Duration, msg string) Middleware { return func(next http.Handler) http.Handler { return http.TimeoutHandler(next, dt, msg) } }
func main() { // This should be a http.Handle("/testfiles/", http.TimeoutHandler(&rescat.HandleFS{}, time.Nanosecond, "")) log.Fatal(http.ListenAndServe(":8888", nil)) }
func registerHandlers(mux *http.ServeMux, db *sql.DB) { runs, err := context().QueueManager.Get("default") if err != nil { panic(err) } mux.Handle("/", http.FileServer(&wrappedFileSystem{ fileSystem: &assetfs.AssetFS{ Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "data", }, })) mux.HandleFunc("/monitoring/benchmark/", func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() ctx := context() runnerName := PeerName(r) f, err := os.OpenFile("benchmark.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664) if err != nil { ctx.Log.Error("Failed to open benchmark file", "err", err) return } defer f.Close() var buf bytes.Buffer buf.WriteString(fmt.Sprintf("%d %s ", time.Now().Unix(), runnerName)) io.Copy(&buf, r.Body) buf.WriteString("\n") if _, err := io.Copy(f, &buf); err != nil { ctx.Log.Error("Failed to write to benchmark file", "err", err) } }) gradeRe := regexp.MustCompile("/run/grade/(\\d+)/?") mux.HandleFunc("/run/grade/", func(w http.ResponseWriter, r *http.Request) { ctx := context() res := gradeRe.FindStringSubmatch(r.URL.Path) if res == nil { w.WriteHeader(http.StatusNotFound) return } id, err := strconv.ParseInt(res[1], 10, 64) if err != nil { w.WriteHeader(http.StatusNotFound) return } runCtx, err := newRunContext(ctx, db, id) if err != nil { ctx.Log.Error("Error getting run context", "err", err, "id", id) if err == sql.ErrNoRows { w.WriteHeader(http.StatusNotFound) } else { w.WriteHeader(http.StatusInternalServerError) } return } input, err := ctx.InputManager.Add( runCtx.Run.InputHash, grader.NewGraderInputFactory(runCtx.ProblemName, &ctx.Config), ) if err != nil { ctx.Log.Error("Error getting input", "err", err, "run", runCtx) w.WriteHeader(http.StatusInternalServerError) return } if err = grader.AddRunContext(ctx, runCtx, input); err != nil { ctx.Log.Error("Error adding run context", "err", err, "id", id) w.WriteHeader(http.StatusInternalServerError) return } if _, ok := r.URL.Query()["debug"]; ok { if err := runCtx.Debug(); err != nil { ctx.Log.Error("Unable to set debug mode", "err", err) } else { defer func() { if err := os.RemoveAll(runCtx.GradeDir); err != nil { ctx.Log.Error("Error writing response", "err", err) } }() } } runs.AddRun(runCtx) runCtx.Log.Info("enqueued run", "run", runCtx.Run) if _, ok := r.URL.Query()["wait"]; ok { select { case <-w.(http.CloseNotifier).CloseNotify(): return case <-runCtx.Ready(): } if _, ok := r.URL.Query()["multipart"]; ok { multipartWriter := multipart.NewWriter(w) defer multipartWriter.Close() w.Header().Set("Content-Type", multipartWriter.FormDataContentType()) files := []string{"logs.txt.gz", "files.zip", "details.json", "tracing.json.gz"} for _, file := range files { fd, err := os.Open(path.Join(runCtx.GradeDir, file)) if err != nil { ctx.Log.Error("Error opening file", "file", file, "err", err) continue } resultWriter, err := multipartWriter.CreateFormFile("file", file) if err != nil { ctx.Log.Error("Error sending file", "file", file, "err", err) continue } if _, err := io.Copy(resultWriter, fd); err != nil { ctx.Log.Error("Error sending file", "file", file, "err", err) continue } } } else { w.Header().Set("Content-Type", "text/json; charset=utf-8") jsonData, _ := json.MarshalIndent(runCtx.Result, "", " ") logData, err := readGzippedFile(path.Join(runCtx.GradeDir, "logs.txt.gz")) if err != nil { ctx.Log.Error("Error reading logs", "err", err) } filesZip, err := readBase64File(path.Join(runCtx.GradeDir, "files.zip")) if err != nil { ctx.Log.Error("Error reading logs", "err", err) } tracing, err := readBase64File(path.Join(runCtx.GradeDir, "tracing.json.gz")) if err != nil { ctx.Log.Error("Error reading logs", "err", err) } response := &ResponseStruct{ Results: string(jsonData), Logs: logData, FilesZip: filesZip, Tracing: tracing, } encoder := json.NewEncoder(w) if err := encoder.Encode(response); err != nil { ctx.Log.Error("Error writing response", "err", err) } } } else { w.Header().Set("Content-Type", "text/json; charset=utf-8") fmt.Fprintf(w, "{\"status\":\"ok\"}") } }) mux.HandleFunc("/run/request/", func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() ctx := context() runnerName := PeerName(r) ctx.Log.Debug("requesting run", "proto", r.Proto, "client", runnerName) runCtx, _, ok := runs.GetRun( runnerName, ctx.InflightMonitor, w.(http.CloseNotifier).CloseNotify(), ) if !ok { ctx.Log.Debug("client gone", "client", runnerName) } else { runCtx.Log.Debug("served run", "run", runCtx, "client", runnerName) w.Header().Set("Content-Type", "text/json; charset=utf-8") ev := runCtx.EventFactory.NewIssuerClockSyncEvent() w.Header().Set("Sync-ID", strconv.FormatUint(ev.SyncID, 10)) encoder := json.NewEncoder(w) encoder.Encode(runCtx.Run) runCtx.EventCollector.Add(ev) } }) runRe := regexp.MustCompile("/run/([0-9]+)/results/?") mux.Handle("/run/", http.TimeoutHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := context() defer r.Body.Close() res := runRe.FindStringSubmatch(r.URL.Path) if res == nil { w.WriteHeader(http.StatusNotFound) return } attemptID, _ := strconv.ParseUint(res[1], 10, 64) runCtx, _, ok := ctx.InflightMonitor.Get(attemptID) if !ok { w.WriteHeader(http.StatusNotFound) return } result := processRun(r, attemptID, runCtx) w.WriteHeader(result.status) if !result.retry { // The run either finished correctly or encountered a fatal error. // Close the context and write the results to disk. runCtx.Close() } else { runCtx.Log.Error("run errored out. retrying", "context", runCtx) // status is OK only when the runner successfully sent a JE verdict. lastAttempt := result.status == http.StatusOK if !runCtx.Requeue(lastAttempt) { runCtx.Log.Error("run errored out too many times. giving up") } } }), time.Duration(5*time.Minute), "Request timed out")) inputRe := regexp.MustCompile("/input/([a-f0-9]{40})/?") mux.HandleFunc("/input/", func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() ctx := context() res := inputRe.FindStringSubmatch(r.URL.Path) if res == nil { w.WriteHeader(http.StatusNotFound) return } hash := res[1] input, err := ctx.InputManager.Get(hash) if err != nil { ctx.Log.Error("Input not found", "hash", hash) w.WriteHeader(http.StatusNotFound) return } defer input.Release(input) if err := input.Transmit(w); err != nil { ctx.Log.Error("Error transmitting input", "hash", hash, "err", err) w.WriteHeader(http.StatusInternalServerError) } }) }
func timeoutHandler(h http.Handler) http.Handler { return http.TimeoutHandler(h, 1*time.Second, "timed out") }
// InitializeService initializes the service with the // provided config and starts it. The channel returned // allows the calller to wait for a message from the running // service. Messages are of type ServiceMessage above. // It can be used for launching service from tests, etc. func InitializeService(service Service, config ServiceConfig) (chan ServiceMessage, string, error) { err := service.SetConfig(config) if err != nil { return nil, "", err } err = service.Initialize() if err != nil { return nil, "", err } // Create negroni negroni := negroni.New() // Add authentication middleware negroni.Use(NewAuth()) // Add content-negotiation middleware. // This is an example of using a middleware. // This will modify the response header to the // negotiated content type, and can then be used as // ct := w.Header().Get("Content-Type") // where w is http.ResponseWriter negroni.Use(NewNegotiator()) // Unmarshal data from the content-type format // into a map negroni.Use(NewUnmarshaller()) routes := service.Routes() router := newRouter(routes) timeoutMillis := config.Common.Api.RestTimeoutMillis var dur time.Duration var readWriteDur time.Duration if timeoutMillis <= 0 { timeoutMillis = DefaultRestTimeout dur = DefaultRestTimeout * time.Millisecond readWriteDur = (DefaultRestTimeout + ReadWriteTimeoutDelta) * time.Millisecond log.Printf("%s: Invalid timeout %d, defaulting to %d\n", service.Name(), timeoutMillis, dur) } else { timeoutStr := fmt.Sprintf("%dms", timeoutMillis) dur, _ = time.ParseDuration(timeoutStr) timeoutStr = fmt.Sprintf("%dms", timeoutMillis+ReadWriteTimeoutDelta) readWriteDur, _ = time.ParseDuration(timeoutStr) } log.Printf("%s: Creating TimeoutHandler with %v\n", service.Name(), dur) timeoutHandler := http.TimeoutHandler(router, dur, TimeoutMessage) negroni.UseHandler(timeoutHandler) hostPort := config.Common.Api.GetHostPort() log.Println("About to start...") ch, addr, err := RunNegroni(negroni, hostPort, readWriteDur) if err == nil { if addr != hostPort { log.Printf("Requested address %s, real %s\n", hostPort, addr) idx := strings.LastIndex(addr, ":") config.Common.Api.Host = addr[0:idx] port, _ := strconv.Atoi(addr[idx+1:]) port64 := uint64(port) config.Common.Api.Port = port64 // Also register this with root service url := fmt.Sprintf("%s/config/%s/port", config.Common.Api.RootServiceUrl, service.Name()) result := make(map[string]interface{}) portMsg := PortUpdateMessage{Port: port64} client, err := NewRestClient("", timeoutMillis) if err != nil { return ch, addr, err } err = client.Post(url, portMsg, &result) } } return ch, addr, err }