Example #1
0
func broadcastChannelOp(op string, req *http.Request) (err error) {
	reqParams, err := http_api.NewReqParams(req)
	if err != nil {
		return
	}

	topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams)
	if err != nil {
		return
	}

	for _, addr := range getAllProducersHttpAddr(topicName) {
		req_url := fmt.Sprintf("%s%s?topic=%s&channel=%s", addr, op, topicName, channelName)

		resp, err := http.PostForm(req_url, url.Values{})
		if err != nil {
			log.Printf("request nsqd fail %s %s", req_url, err.Error())
			return err
		}
		defer resp.Body.Close()

		respBody, err := ioutil.ReadAll(resp.Body)
		log.Printf("request nsqd %s [%s] %v", req_url, string(respBody), err)
	}

	return nil
}
Example #2
0
func PubHandler(w http.ResponseWriter, req *http.Request) {
	reqParams, err := http_api.NewReqParams(req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	topicName, err := reqParams.Get("topic")
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	data := reqParams.Body
	if len(data) == 0 {
		http.Error(w, "empty message payload", http.StatusBadRequest)
		return
	}

	for _, addr := range getAllProducersHttpAddr("") {
		resp, err := http.Post(addr+"/pub?topic="+topicName, "text/plain", bytes.NewReader(data))
		log.Println("pub to ", addr, topicName)
		if err != nil {
			log.Println("pub failed ", addr, topicName, err)
			//try next producer
			continue
		} else {
			resp.Body.Close()
			w.Write([]byte("OK"))
			return
		}
	}
	http.Error(w, err.Error(), http.StatusInternalServerError)
}
Example #3
0
func SubHandler(w http.ResponseWriter, req *http.Request) {
	reqParams, err := http_api.NewReqParams(req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "httpserver doesn't support hijacking", http.StatusInternalServerError)
		return
	}
	conn, bufrw, err := hj.Hijack()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	cfg := nsq.NewConfig()
	cfg.UserAgent = fmt.Sprintf("nsq_httpsub go-nsq/%s", nsq.VERSION)
	cfg.MaxInFlight = *maxInFlight
	r, err := nsq.NewConsumer(topicName, channelName, cfg)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	r.SetLogger(log.New(os.Stderr, "", log.LstdFlags), nsq.LogLevelInfo)

	sr := &StreamReader{
		topic:       topicName,
		channel:     channelName,
		consumer:    r,
		req:         req,
		conn:        conn,
		bufrw:       bufrw, // TODO: latency writer
		connectTime: time.Now(),
	}
	streamServer.Set(sr)

	log.Printf("[%s] new connection", conn.RemoteAddr().String())
	bufrw.WriteString("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n")
	bufrw.Flush()

	r.AddHandler(sr)

	// TODO: handle the error cases better (ie. at all :) )
	errors := ConnectToNSQAndLookupd(r, lookupdHTTPAddrs)
	log.Printf("connected to NSQ %v", errors)

	if *timeout > 0 {
		go func(sr *StreamReader) {
			timer := time.AfterFunc(time.Duration(*timeout)*time.Second, func() {
				log.Printf("timeout after %d seconds", *timeout)
				sr.consumer.Stop()
			})
			for {
				select {
				case <-sr.consumer.StopChan:
					timer.Stop()
					return
				}
			}
		}(sr)
	}

	go sr.HeartbeatLoop()

	// this read allows us to detect clients that disconnect
	go func(rw *bufio.ReadWriter) {
		b, err := rw.ReadByte()
		if err != nil {
			log.Printf("disconnect client %s", err.Error())
		} else {
			log.Printf("unexpected data on request socket (%c); closing", b)
		}
		sr.consumer.Stop()
	}(bufrw)
}