示例#1
0
func (r *Runner) getBuildLog(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	id := ps.ByName("build")
	b := &Build{}
	if err := r.db.View(func(tx *bolt.Tx) error {
		v := tx.Bucket(dbBucket).Get([]byte(id))
		if err := json.Unmarshal(v, b); err != nil {
			return fmt.Errorf("could not decode build %s: %s", v, err)
		}
		return nil
	}); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// if it's a V1 build, redirect to the log in S3
	if b.Version == BuildVersion1 {
		http.Redirect(w, req, b.LogURL, http.StatusMovedPermanently)
		return
	}

	// if it's a browser, serve the build-log.html template
	if strings.Contains(req.Header.Get("Accept"), "text/html") {
		tpl, err := template.ParseFiles(path.Join(args.AssetsDir, "build-log.html"))
		if err != nil {
			http.Error(w, err.Error(), 500)
			return
		}
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		if err := tpl.Execute(w, b); err != nil {
			log.Printf("error executing build-log template: %s", err)
		}
		return
	}

	// serve the build log as either an SSE or plain text stream
	ch := make(chan string)
	stream, err := getBuildLogStream(b, ch)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	if cn, ok := w.(http.CloseNotifier); ok {
		go func() {
			<-cn.CloseNotify()
			stream.Close()
		}()
	} else {
		defer stream.Close()
	}

	if strings.Contains(req.Header.Get("Accept"), "text/event-stream") {
		sse.ServeStream(w, ch, nil)
	} else {
		servePlainStream(w, ch)
	}

	if err := stream.Err(); err != nil {
		log.Println("error serving build log stream:", err)
	}
}
示例#2
0
func (api *httpAPI) Events(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	eventChan := make(chan *Event)
	lastEventID := req.Header.Get("Last-Event-ID")
	sub := api.Installer.Subscribe(eventChan, lastEventID)
	defer api.Installer.Unsubscribe(sub)
	sse.ServeStream(w, eventChan, api.logger)
}
示例#3
0
文件: api.go 项目: ably-forks/flynn
func (api *API) StreamEvents(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	log, _ := ctxhelper.LoggerFromContext(ctx)

	httpListener := api.router.ListenerFor("http")
	tcpListener := api.router.ListenerFor("tcp")

	httpEvents := make(chan *router.Event)
	tcpEvents := make(chan *router.Event)
	sseEvents := make(chan *router.StreamEvent)
	go httpListener.Watch(httpEvents)
	go tcpListener.Watch(tcpEvents)
	defer httpListener.Unwatch(httpEvents)
	defer tcpListener.Unwatch(tcpEvents)
	sendEvents := func(events chan *router.Event) {
		for {
			e, ok := <-events
			if !ok {
				return
			}
			sseEvents <- &router.StreamEvent{
				Event: e.Event,
				Route: e.Route,
				Error: e.Error,
			}
		}
	}
	go sendEvents(httpEvents)
	go sendEvents(tcpEvents)
	sse.ServeStream(w, sseEvents, log)
}
示例#4
0
文件: api.go 项目: supermario/flynn
func streamEvents(params martini.Params, rtr *Router, w http.ResponseWriter) {
	httpListener := listenerFor(rtr, "http")
	tcpListener := listenerFor(rtr, "tcp")

	log := log15.New("component", "router")
	httpEvents := make(chan *router.Event)
	tcpEvents := make(chan *router.Event)
	sseEvents := make(chan *router.StreamEvent)
	go httpListener.Watch(httpEvents)
	go tcpListener.Watch(tcpEvents)
	defer httpListener.Unwatch(httpEvents)
	defer tcpListener.Unwatch(tcpEvents)
	sendEvents := func(events chan *router.Event) {
		for {
			e, ok := <-events
			if !ok {
				return
			}
			sseEvents <- &router.StreamEvent{
				Event: e.Event,
				Route: e.Route,
				Error: e.Error,
			}
		}
	}
	go sendEvents(httpEvents)
	go sendEvents(tcpEvents)
	sse.ServeStream(w, sseEvents, log)
}
示例#5
0
文件: formation.go 项目: devick/flynn
func (c *controllerAPI) streamFormations(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	ch := make(chan *ct.ExpandedFormation)
	since, err := time.Parse(time.RFC3339, req.FormValue("since"))
	if err != nil {
		respondWithError(w, err)
		return
	}
	sub, err := c.formationRepo.Subscribe(ch, since, nil)
	if err != nil {
		respondWithError(w, err)
		return
	}
	defer c.formationRepo.Unsubscribe(sub)
	l, _ := ctxhelper.LoggerFromContext(ctx)
	sse.ServeStream(w, ch, l)
}
示例#6
0
文件: api.go 项目: imjorge/flynn
func (api *API) StreamEvents(ctx context.Context, w http.ResponseWriter, req *http.Request) {
	log, _ := ctxhelper.LoggerFromContext(ctx)

	httpListener := api.router.ListenerFor("http")
	tcpListener := api.router.ListenerFor("tcp")

	httpEvents := make(chan *router.Event)
	tcpEvents := make(chan *router.Event)
	sseEvents := make(chan *router.StreamEvent)
	go httpListener.Watch(httpEvents, true)
	go tcpListener.Watch(tcpEvents, true)
	defer httpListener.Unwatch(httpEvents)
	defer tcpListener.Unwatch(tcpEvents)

	reqTypes := strings.Split(req.URL.Query().Get("types"), ",")
	eventTypes := make(map[router.EventType]struct{}, len(reqTypes))
	for _, typ := range reqTypes {
		eventTypes[router.EventType(typ)] = struct{}{}
	}

	sendEvents := func(events chan *router.Event) {
		for {
			e, ok := <-events
			if !ok {
				return
			}
			if _, ok := eventTypes[e.Event]; !ok {
				continue
			}
			sseEvents <- &router.StreamEvent{
				Event:   e.Event,
				Route:   e.Route,
				Backend: e.Backend,
				Error:   e.Error,
			}
		}
	}
	go sendEvents(httpEvents)
	go sendEvents(tcpEvents)
	sse.ServeStream(w, sseEvents, log)
}
示例#7
0
文件: http.go 项目: imjorge/flynn
func (h *Host) streamEvents(id string, w http.ResponseWriter) error {
	ch := h.state.AddListener(id)
	defer h.state.RemoveListener(id, ch)
	sse.ServeStream(w, ch, nil)
	return nil
}