Example #1
0
func (self *Pump) runMsger(msgerName string, resp http.ResponseWriter, allowCrossDomain bool) {
	var msger *messenger.Messenger
	if self.msgers[msgerName] == nil {
		msger = messenger.New(msgerName)
		self.RegisterMessenger(msgerName, msger)
		// TODO: fix display format to subscribe/events/id
		log.Println("SSE endpoint: listening /subscribe/" + msger.Name())
	} else {
		msger = self.msgers[msgerName]
	}

	go self.subscribeRedis(msgerName, msger)

	// Make sure that the writer supports flushing.
	//
	f, ok := resp.(http.Flusher)
	if !ok {
		http.Error(resp, "Streaming unsupported", http.StatusInternalServerError)
		return
	}
	c, ok := resp.(http.CloseNotifier)
	if !ok {
		http.Error(resp, "Close notification unsupported", http.StatusInternalServerError)
		return
	}
	closer := c.CloseNotify()

	// Create a new channel, over which the broker can
	// send self client messages.
	messageChan := make(chan string)

	// Add self client to the map of those that should
	// receive updates
	msger.AddClient(messageChan)

	// Remove self client from the map of attached clients
	// when `EventHandler` exits.
	defer func() {
		msger.RemoveClient(messageChan)
	}()

	// Set the headers related to event streaming.
	resp.Header().Set("Content-Type", "text/event-stream")
	resp.Header().Set("Cache-Control", "no-cache")
	resp.Header().Set("Connection", "keep-alive")
	if allowCrossDomain {
		resp.Header().Set("Access-Control-Allow-Origin", "*")
	}

	// Use the CloseNotifier interface
	// https://code.google.com/p/go/source/detail?name=3292433291b2
	//
	// NOTE: we could loop endlessly; however, then you
	// could not easily detect clients that dettach and the
	// server would continue to send them messages long after
	// they're gone due to the "keep-alive" header.  One of
	// the nifty aspects of SSE is that clients automatically
	// reconnect when they lose their connection.
	//
	for {
		select {
		case msg := <-messageChan:
			fmt.Fprintf(resp, "data: %s\n\n", msg)
			f.Flush()
		case <-closer:
			log.Println("Closing connection")
			return
		}
	}
}