func generateRandomEvents(lpManager *golongpoll.LongpollManager) { farm_events := []string{ "Cow says 'Moooo!'", "Duck went 'Quack!'", "Chicken says: 'Cluck!'", "Goat chewed grass.", "Pig went 'Oink! Oink!'", "Horse ate hay.", "Tractor went: Vroom Vroom!", "Farmer ate bacon.", } // every 0-5 seconds, something happens at the farm: for { time.Sleep(time.Duration(rand.Intn(5000)) * time.Millisecond) lpManager.Publish("farm", farm_events[rand.Intn(len(farm_events))]) } }
func notifyProxyEvent(action string, req *http.Request, lpManager *golongpoll.LongpollManager) { // in the event localhost isn't added to noproxy, don't emit localhost event normUrl := strings.ToLower(req.URL.String()) if strings.HasPrefix(normUrl, "http://127.0.0.1:") || strings.HasPrefix(normUrl, "http://127.0.0.1/") || strings.HasPrefix(normUrl, "127.0.0.1:") || strings.HasPrefix(normUrl, "127.0.0.1/") { // no events for you! return } var category string if referer := req.Header.Get("Referer"); len(referer) > 0 { category = utils.StripProxyExceptionStringFromUrl(referer) } else { category = utils.StripProxyExceptionStringFromUrl(req.URL.String()) } eventData := action + ": " + req.URL.String() if err := lpManager.Publish(category, eventData); err != nil { log.Printf("ERROR: failed to publish event. error: %q", err) } }
// Creates a closure function that is used as an http handler for browsers to // subscribe to events via longpolling. // Notice how we're wrapping LongpollManager.SubscriptionHandler in order to // add our own logic and validation. func getEventSubscriptionHandler(manager *golongpoll.LongpollManager) func(w http.ResponseWriter, r *http.Request) { // Creates closure that captures the LongpollManager // Wraps the manager.SubscriptionHandler with a layer of dummy access control validation return func(w http.ResponseWriter, r *http.Request) { category := r.URL.Query().Get("category") user := r.URL.Query().Get("user") // NOTE: real user authentication should be used in the real world! // Dummy user access control in the event the client is requesting // a user's private activity stream: if category == "larry_actions" && user != "larry" { w.WriteHeader(http.StatusForbidden) w.Write([]byte("You're not Larry.")) return } if category == "moe_actions" && user != "moe" { w.WriteHeader(http.StatusForbidden) w.Write([]byte("You're not Moe.")) return } if category == "curly_actions" && user != "curly" { w.WriteHeader(http.StatusForbidden) w.Write([]byte("You're not Curly.")) return } // Only allow supported subscription categories: if category != "public_actions" && category != "larry_actions" && category != "moe_actions" && category != "curly_actions" { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Subscription channel does not exist.")) return } // Client is either requesting the public stream, or a private // stream that they're allowed to see. // Go ahead and let the subscription happen: manager.SubscriptionHandler(w, r) } }
// Creates a closure function that is used as an http handler that allows // users to publish events (what this example is calling a user action event) func getUserActionHandler(manager *golongpoll.LongpollManager) func(w http.ResponseWriter, r *http.Request) { // Creates closure that captures the LongpollManager return func(w http.ResponseWriter, r *http.Request) { user := r.URL.Query().Get("user") action := r.URL.Query().Get("action") public := r.URL.Query().Get("public") // Perform validation on url query params: if len(user) == 0 || len(action) == 0 { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Missing required URL param.")) return } if user != "larry" && user != "moe" && user != "curly" { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Not a user.")) return } if len(public) > 0 && public != "true" { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Optional param 'public' must be 'true' if present.")) return } // convert string arg to bool isPublic := false if public == "true" { isPublic = true } actionEvent := UserAction{User: user, Action: action, IsPublic: isPublic} // Publish on public subscription channel if the action is public. // Everyone can see this event. if isPublic { manager.Publish("public_actions", actionEvent) } // Publish on user's private channel regardless // Only the user that called this will see the event. manager.Publish(user+"_actions", actionEvent) } }