func deleteChannelHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := util.NewReqParams(req) if err != nil { util.ApiResponse(w, 500, "INVALID_REQUEST", nil) return } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { util.ApiResponse(w, 500, err.Error(), nil) return } registrations := lookupd.DB.FindRegistrations("channel", topicName, channelName) if len(registrations) == 0 { util.ApiResponse(w, 404, "NOT_FOUND", nil) return } log.Printf("DB: removing channel(%s) from topic(%s)", channelName, topicName) for _, registration := range registrations { lookupd.DB.RemoveRegistration(*registration) } util.ApiResponse(w, 200, "OK", nil) }
func (s *httpServer) pauseChannelHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := util.NewReqParams(req) if err != nil { log.Printf("ERROR: failed to parse request params - %s", err.Error()) util.ApiResponse(w, 500, "INVALID_REQUEST", nil) return } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { util.ApiResponse(w, 500, err.Error(), nil) return } topic, err := s.context.nsqd.GetExistingTopic(topicName) if err != nil { util.ApiResponse(w, 500, "INVALID_TOPIC", nil) return } channel, err := topic.GetExistingChannel(channelName) if err != nil { util.ApiResponse(w, 500, "INVALID_CHANNEL", nil) return } if strings.HasPrefix(req.URL.Path, "/pause") { channel.Pause() } else { channel.UnPause() } util.ApiResponse(w, 200, "OK", nil) }
func (s *httpServer) pauseChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Printf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } producers := s.getProducers(topicName) for _, addr := range producers { endpoint := fmt.Sprintf("http://%s%s?topic=%s&channel=%s", addr, req.URL.Path, url.QueryEscape(topicName), url.QueryEscape(channelName)) log.Printf("NSQD: calling %s", endpoint) _, err := util.ApiRequest(endpoint) if err != nil { log.Printf("ERROR: nsqd %s - %s", endpoint, err.Error()) continue } } s.notifyAdminAction(strings.TrimLeft(req.URL.Path, "/"), topicName, channelName, "", req) http.Redirect(w, req, fmt.Sprintf("/topic/%s/%s", url.QueryEscape(topicName), url.QueryEscape(channelName)), 302) }
func (s *httpServer) deleteChannelHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := util.NewReqParams(req) if err != nil { log.Printf("ERROR: failed to parse request params - %s", err.Error()) util.ApiResponse(w, 500, "INVALID_REQUEST", nil) return } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { util.ApiResponse(w, 500, err.Error(), nil) return } topic, err := s.context.nsqd.GetExistingTopic(topicName) if err != nil { util.ApiResponse(w, 500, "INVALID_TOPIC", nil) return } err = topic.DeleteExistingChannel(channelName) if err != nil { util.ApiResponse(w, 500, "INVALID_CHANNEL", nil) return } util.ApiResponse(w, 200, "OK", nil) }
func (s *httpServer) pauseChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } verb := "pause" if strings.Contains(req.URL.Path, "unpause") { verb = "unpause" } producerAddrs := s.getProducers(topicName) s.performVersionNegotiatedRequestsToNSQD( s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, producerAddrs, verb+"_channel", "channel/"+verb, fmt.Sprintf("topic=%s&channel=%s", url.QueryEscape(topicName), url.QueryEscape(channelName))) s.notifyAdminAction(verb+"_channel", topicName, channelName, "", req) http.Redirect(w, req, fmt.Sprintf("/topic/%s/%s", url.QueryEscape(topicName), url.QueryEscape(channelName)), 302) }
func (s *httpServer) emptyChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Printf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } producerAddrs := s.getProducers(topicName) performVersionNegotiatedRequestsToNSQD( s.context.nsqadmin.options.NSQLookupdHTTPAddresses, producerAddrs, "empty_channel", "channel/empty", fmt.Sprintf("topic=%s&channel=%s", url.QueryEscape(topicName), url.QueryEscape(channelName))) s.notifyAdminAction("empty_channel", topicName, channelName, "", req) http.Redirect(w, req, fmt.Sprintf("/topic/%s/%s", url.QueryEscape(topicName), url.QueryEscape(channelName)), 302) }
func emptyChannelHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := util.NewReqParams(req) if err != nil { log.Printf("ERROR: failed to parse request params - %s", err.Error()) util.ApiResponse(w, 500, "INVALID_REQUEST", nil) return } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { util.ApiResponse(w, 500, err.Error(), nil) return } topic, err := nsqd.GetExistingTopic(topicName) if err != nil { util.ApiResponse(w, 500, "INVALID_TOPIC", nil) return } channel, err := topic.GetExistingChannel(channelName) if err != nil { util.ApiResponse(w, 500, "INVALID_CHANNEL", nil) return } err = channel.Empty() if err != nil { util.ApiResponse(w, 500, "INTERNAL_ERROR", nil) return } util.ApiResponse(w, 200, "OK", nil) }
func (s *httpServer) deleteChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = fmt.Sprintf("/topic/%s", url.QueryEscape(topicName)) } for _, addr := range s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses { nsqlookupdVersion, err := lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqlookupd %s version - %s", addr, err) } uri := "delete_channel" if !nsqlookupdVersion.Less(v1EndpointVersion) { uri = "channel/delete" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s&channel=%s", addr, uri, url.QueryEscape(topicName), url.QueryEscape(channelName)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err = util.APIRequestNegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) continue } } producerAddrs := s.getProducers(topicName) s.performVersionNegotiatedRequestsToNSQD( s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, producerAddrs, "delete_channel", "channel/delete", fmt.Sprintf("topic=%s&channel=%s", url.QueryEscape(topicName), url.QueryEscape(channelName))) s.notifyAdminAction("delete_channel", topicName, channelName, "", req) http.Redirect(w, req, rd, 302) }
func deleteChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Printf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = fmt.Sprintf("/topic/%s", url.QueryEscape(topicName)) } for _, addr := range lookupdHTTPAddrs { endpoint := fmt.Sprintf("http://%s/delete_channel?topic=%s&channel=%s", addr, url.QueryEscape(topicName), url.QueryEscape(channelName)) log.Printf("LOOKUPD: querying %s", endpoint) _, err := nsq.ApiRequest(endpoint) if err != nil { log.Printf("ERROR: lookupd %s - %s", endpoint, err.Error()) continue } } var producers []string if len(lookupdHTTPAddrs) != 0 { producers, _ = getLookupdTopicProducers(topicName, lookupdHTTPAddrs) } else { producers, _ = getNSQDTopicProducers(topicName, nsqdHTTPAddrs) } for _, addr := range producers { endpoint := fmt.Sprintf("http://%s/delete_channel?topic=%s&channel=%s", addr, url.QueryEscape(topicName), url.QueryEscape(channelName)) log.Printf("NSQD: querying %s", endpoint) _, err := nsq.ApiRequest(endpoint) if err != nil { log.Printf("ERROR: nsqd %s - %s", endpoint, err.Error()) continue } } NotifyAdminAction("delete_channel", topicName, channelName, req) http.Redirect(w, req, rd, 302) }
func (s *httpServer) deleteChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Printf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &util.PostParams{req} topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = fmt.Sprintf("/topic/%s", url.QueryEscape(topicName)) } for _, addr := range s.context.nsqadmin.options.NSQLookupdHTTPAddresses { endpoint := fmt.Sprintf("http://%s/delete_channel?topic=%s&channel=%s", addr, url.QueryEscape(topicName), url.QueryEscape(channelName)) log.Printf("LOOKUPD: querying %s", endpoint) _, err := util.ApiRequest(endpoint) if err != nil { log.Printf("ERROR: lookupd %s - %s", endpoint, err.Error()) continue } } producers := s.getProducers(topicName) for _, addr := range producers { endpoint := fmt.Sprintf("http://%s/delete_channel?topic=%s&channel=%s", addr, url.QueryEscape(topicName), url.QueryEscape(channelName)) log.Printf("NSQD: querying %s", endpoint) _, err := util.ApiRequest(endpoint) if err != nil { log.Printf("ERROR: nsqd %s - %s", endpoint, err.Error()) continue } } s.notifyAdminAction("delete_channel", topicName, channelName, "", req) http.Redirect(w, req, rd, 302) }
func (s *httpServer) getExistingTopicFromQuery(req *http.Request) (*util.ReqParams, *Topic, string, error) { reqParams, err := util.NewReqParams(req) if err != nil { log.Printf("ERROR: failed to parse request params - %s", err) return nil, nil, "", httpError{400, "INVALID_REQUEST"} } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { return nil, nil, "", httpError{400, err.Error()} } topic, err := s.context.nsqd.GetExistingTopic(topicName) if err != nil { return nil, nil, "", httpError{404, "TOPIC_NOT_FOUND"} } return reqParams, topic, channelName, err }
func (s *httpServer) doCreateChannel(req *http.Request) (interface{}, error) { reqParams, err := util.NewReqParams(req) if err != nil { return nil, util.HTTPError{400, "INVALID_REQUEST"} } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { return nil, util.HTTPError{400, err.Error()} } log.Printf("DB: adding channel(%s) in topic(%s)", channelName, topicName) key := Registration{"channel", topicName, channelName} s.context.nsqlookupd.DB.AddRegistration(key) log.Printf("DB: adding topic(%s)", topicName) key = Registration{"topic", topicName, ""} s.context.nsqlookupd.DB.AddRegistration(key) return nil, nil }
func createChannelHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := util.NewReqParams(req) if err != nil { util.ApiResponse(w, 500, "INVALID_REQUEST", nil) return } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { util.ApiResponse(w, 500, err.Error(), nil) return } log.Printf("DB: adding channel(%s) in topic(%s)", channelName, topicName) key := Registration{"channel", topicName, channelName} lookupd.DB.AddRegistration(key) log.Printf("DB: adding topic(%s)", topicName) key = Registration{"topic", topicName, ""} lookupd.DB.AddRegistration(key) util.ApiResponse(w, 200, "OK", nil) }
func (s *httpServer) doDeleteChannel(req *http.Request) (interface{}, error) { reqParams, err := util.NewReqParams(req) if err != nil { return nil, util.HTTPError{400, "INVALID_REQUEST"} } topicName, channelName, err := util.GetTopicChannelArgs(reqParams) if err != nil { return nil, util.HTTPError{400, err.Error()} } registrations := s.context.nsqlookupd.DB.FindRegistrations("channel", topicName, channelName) if len(registrations) == 0 { return nil, util.HTTPError{404, "CHANNEL_NOT_FOUND"} } log.Printf("DB: removing channel(%s) from topic(%s)", channelName, topicName) for _, registration := range registrations { s.context.nsqlookupd.DB.RemoveRegistration(registration) } return nil, nil }
func (s *StreamServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { path := req.URL.Path if path == "/stats" { StatsHandler(w, req) return } if path != "/sub" { w.WriteHeader(404) return } reqParams, err := util.NewReqParams(req) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } topicName, channelName, err := util.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_pubsub/%s go-nsq/%s", util.BINARY_VERSION, 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(), } s.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.SetHandler(sr) // TODO: handle the error cases better (ie. at all :) ) errors := ConnectToNSQAndLookupd(r, nsqdTCPAddrs, lookupdHTTPAddrs) log.Printf("connected to NSQ %v", errors) // this read allows us to detect clients that disconnect go func(rw *bufio.ReadWriter) { b, err := rw.ReadByte() if err != nil { log.Printf("got connection err %s", err.Error()) } else { log.Printf("unexpected data on request socket (%s); closing", b) } sr.consumer.Stop() }(bufrw) go sr.HeartbeatLoop() }