github.com/nsqio/nsq@v1.3.0/nsqadmin/http_test.go (about)

     1  package nsqadmin
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  	"net/http"
    10  	"os"
    11  	"strconv"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/nsqio/nsq/internal/clusterinfo"
    16  	"github.com/nsqio/nsq/internal/test"
    17  	"github.com/nsqio/nsq/internal/version"
    18  	"github.com/nsqio/nsq/nsqd"
    19  	"github.com/nsqio/nsq/nsqlookupd"
    20  )
    21  
    22  type TopicsDoc struct {
    23  	Topics []interface{} `json:"topics"`
    24  }
    25  
    26  type TopicStatsDoc struct {
    27  	*clusterinfo.TopicStats
    28  	Message string `json:"message"`
    29  }
    30  
    31  type NodesDoc struct {
    32  	Nodes   clusterinfo.Producers `json:"nodes"`
    33  	Message string                `json:"message"`
    34  }
    35  
    36  type NodeStatsDoc struct {
    37  	Node          string                    `json:"node"`
    38  	TopicStats    []*clusterinfo.TopicStats `json:"topics"`
    39  	TotalMessages int64                     `json:"total_messages"`
    40  	TotalClients  int64                     `json:"total_clients"`
    41  	Message       string                    `json:"message"`
    42  }
    43  
    44  type ChannelStatsDoc struct {
    45  	*clusterinfo.ChannelStats
    46  	Message string `json:"message"`
    47  }
    48  
    49  func mustStartNSQLookupd(opts *nsqlookupd.Options) (*net.TCPAddr, *net.TCPAddr, *nsqlookupd.NSQLookupd) {
    50  	opts.TCPAddress = "127.0.0.1:0"
    51  	opts.HTTPAddress = "127.0.0.1:0"
    52  	lookupd, err := nsqlookupd.New(opts)
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  	go func() {
    57  		err := lookupd.Main()
    58  		if err != nil {
    59  			panic(err)
    60  		}
    61  	}()
    62  	return lookupd.RealTCPAddr(), lookupd.RealHTTPAddr(), lookupd
    63  }
    64  
    65  func bootstrapNSQCluster(t *testing.T) (string, []*nsqd.NSQD, []*nsqlookupd.NSQLookupd, *NSQAdmin) {
    66  	return bootstrapNSQClusterWithAuth(t, false)
    67  }
    68  
    69  func bootstrapNSQClusterWithAuth(t *testing.T, withAuth bool) (string, []*nsqd.NSQD, []*nsqlookupd.NSQLookupd, *NSQAdmin) {
    70  	lgr := test.NewTestLogger(t)
    71  
    72  	nsqlookupdOpts := nsqlookupd.NewOptions()
    73  	nsqlookupdOpts.TCPAddress = "127.0.0.1:0"
    74  	nsqlookupdOpts.HTTPAddress = "127.0.0.1:0"
    75  	nsqlookupdOpts.BroadcastAddress = "127.0.0.1"
    76  	nsqlookupdOpts.Logger = lgr
    77  	nsqlookupd1, err := nsqlookupd.New(nsqlookupdOpts)
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  	go func() {
    82  		err := nsqlookupd1.Main()
    83  		if err != nil {
    84  			panic(err)
    85  		}
    86  	}()
    87  
    88  	time.Sleep(100 * time.Millisecond)
    89  
    90  	nsqdOpts := nsqd.NewOptions()
    91  	nsqdOpts.TCPAddress = "127.0.0.1:0"
    92  	nsqdOpts.HTTPAddress = "127.0.0.1:0"
    93  	nsqdOpts.BroadcastAddress = "127.0.0.1"
    94  	nsqdOpts.NSQLookupdTCPAddresses = []string{nsqlookupd1.RealTCPAddr().String()}
    95  	nsqdOpts.Logger = lgr
    96  	tmpDir, err := os.MkdirTemp("", "nsq-test-")
    97  	if err != nil {
    98  		panic(err)
    99  	}
   100  	nsqdOpts.DataPath = tmpDir
   101  	nsqd1, err := nsqd.New(nsqdOpts)
   102  	if err != nil {
   103  		panic(err)
   104  	}
   105  	go func() {
   106  		err := nsqd1.Main()
   107  		if err != nil {
   108  			panic(err)
   109  		}
   110  	}()
   111  
   112  	nsqadminOpts := NewOptions()
   113  	nsqadminOpts.HTTPAddress = "127.0.0.1:0"
   114  	nsqadminOpts.NSQLookupdHTTPAddresses = []string{nsqlookupd1.RealHTTPAddr().String()}
   115  	nsqadminOpts.Logger = lgr
   116  	if withAuth {
   117  		nsqadminOpts.AdminUsers = []string{"matt"}
   118  	}
   119  	nsqadmin1, err := New(nsqadminOpts)
   120  	if err != nil {
   121  		panic(err)
   122  	}
   123  	go func() {
   124  		err := nsqadmin1.Main()
   125  		if err != nil {
   126  			panic(err)
   127  		}
   128  	}()
   129  
   130  	time.Sleep(100 * time.Millisecond)
   131  
   132  	return tmpDir, []*nsqd.NSQD{nsqd1}, []*nsqlookupd.NSQLookupd{nsqlookupd1}, nsqadmin1
   133  }
   134  
   135  func TestPing(t *testing.T) {
   136  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   137  	defer os.RemoveAll(dataPath)
   138  	defer nsqds[0].Exit()
   139  	defer nsqlookupds[0].Exit()
   140  	defer nsqadmin1.Exit()
   141  
   142  	client := http.Client{}
   143  	url := fmt.Sprintf("http://%s/ping", nsqadmin1.RealHTTPAddr())
   144  	req, _ := http.NewRequest("GET", url, nil)
   145  	resp, err := client.Do(req)
   146  	test.Nil(t, err)
   147  	test.Equal(t, 200, resp.StatusCode)
   148  	body, _ := io.ReadAll(resp.Body)
   149  	resp.Body.Close()
   150  
   151  	test.Equal(t, []byte("OK"), body)
   152  }
   153  
   154  func TestHTTPTopicsGET(t *testing.T) {
   155  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   156  	defer os.RemoveAll(dataPath)
   157  	defer nsqds[0].Exit()
   158  	defer nsqlookupds[0].Exit()
   159  	defer nsqadmin1.Exit()
   160  
   161  	topicName := "test_topics_get" + strconv.Itoa(int(time.Now().Unix()))
   162  	nsqds[0].GetTopic(topicName)
   163  	time.Sleep(100 * time.Millisecond)
   164  
   165  	client := http.Client{}
   166  	url := fmt.Sprintf("http://%s/api/topics", nsqadmin1.RealHTTPAddr())
   167  	req, _ := http.NewRequest("GET", url, nil)
   168  	resp, err := client.Do(req)
   169  	test.Nil(t, err)
   170  	test.Equal(t, 200, resp.StatusCode)
   171  	body, _ := io.ReadAll(resp.Body)
   172  	resp.Body.Close()
   173  
   174  	t.Logf("%s", body)
   175  	tr := TopicsDoc{}
   176  	err = json.Unmarshal(body, &tr)
   177  	test.Nil(t, err)
   178  	test.Equal(t, 1, len(tr.Topics))
   179  	test.Equal(t, topicName, tr.Topics[0])
   180  }
   181  
   182  func TestHTTPTopicGET(t *testing.T) {
   183  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   184  	defer os.RemoveAll(dataPath)
   185  	defer nsqds[0].Exit()
   186  	defer nsqlookupds[0].Exit()
   187  	defer nsqadmin1.Exit()
   188  
   189  	topicName := "test_topic_get" + strconv.Itoa(int(time.Now().Unix()))
   190  	nsqds[0].GetTopic(topicName)
   191  	time.Sleep(100 * time.Millisecond)
   192  
   193  	client := http.Client{}
   194  	url := fmt.Sprintf("http://%s/api/topics/%s", nsqadmin1.RealHTTPAddr(), topicName)
   195  	req, _ := http.NewRequest("GET", url, nil)
   196  	resp, err := client.Do(req)
   197  	test.Nil(t, err)
   198  	test.Equal(t, 200, resp.StatusCode)
   199  	body, _ := io.ReadAll(resp.Body)
   200  	resp.Body.Close()
   201  
   202  	t.Logf("%s", body)
   203  	ts := TopicStatsDoc{}
   204  	err = json.Unmarshal(body, &ts)
   205  	test.Nil(t, err)
   206  	test.Equal(t, topicName, ts.TopicName)
   207  	test.Equal(t, 0, int(ts.Depth))
   208  	test.Equal(t, 0, int(ts.MemoryDepth))
   209  	test.Equal(t, 0, int(ts.BackendDepth))
   210  	test.Equal(t, 0, int(ts.MessageCount))
   211  	test.Equal(t, false, ts.Paused)
   212  }
   213  
   214  func TestHTTPNodesGET(t *testing.T) {
   215  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   216  	defer os.RemoveAll(dataPath)
   217  	defer nsqds[0].Exit()
   218  	defer nsqlookupds[0].Exit()
   219  	defer nsqadmin1.Exit()
   220  
   221  	time.Sleep(100 * time.Millisecond)
   222  
   223  	client := http.Client{}
   224  	url := fmt.Sprintf("http://%s/api/nodes", nsqadmin1.RealHTTPAddr())
   225  	req, _ := http.NewRequest("GET", url, nil)
   226  	resp, err := client.Do(req)
   227  	test.Nil(t, err)
   228  	test.Equal(t, 200, resp.StatusCode)
   229  	body, _ := io.ReadAll(resp.Body)
   230  	resp.Body.Close()
   231  
   232  	hostname, _ := os.Hostname()
   233  
   234  	t.Logf("%s", body)
   235  	ns := NodesDoc{}
   236  	err = json.Unmarshal(body, &ns)
   237  	test.Nil(t, err)
   238  	test.Equal(t, 1, len(ns.Nodes))
   239  	testNode := ns.Nodes[0]
   240  	test.Equal(t, hostname, testNode.Hostname)
   241  	test.Equal(t, "127.0.0.1", testNode.BroadcastAddress)
   242  	test.Equal(t, nsqds[0].RealTCPAddr().(*net.TCPAddr).Port, testNode.TCPPort)
   243  	test.Equal(t, nsqds[0].RealHTTPAddr().(*net.TCPAddr).Port, testNode.HTTPPort)
   244  	test.Equal(t, version.Binary, testNode.Version)
   245  	test.Equal(t, 0, len(testNode.Topics))
   246  }
   247  
   248  func TestHTTPChannelGET(t *testing.T) {
   249  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   250  	defer os.RemoveAll(dataPath)
   251  	defer nsqds[0].Exit()
   252  	defer nsqlookupds[0].Exit()
   253  	defer nsqadmin1.Exit()
   254  
   255  	topicName := "test_channel_get" + strconv.Itoa(int(time.Now().Unix()))
   256  	topic := nsqds[0].GetTopic(topicName)
   257  	topic.GetChannel("ch")
   258  	time.Sleep(100 * time.Millisecond)
   259  
   260  	client := http.Client{}
   261  	url := fmt.Sprintf("http://%s/api/topics/%s/ch", nsqadmin1.RealHTTPAddr(), topicName)
   262  	req, _ := http.NewRequest("GET", url, nil)
   263  	resp, err := client.Do(req)
   264  	test.Nil(t, err)
   265  	test.Equal(t, 200, resp.StatusCode)
   266  	body, _ := io.ReadAll(resp.Body)
   267  	resp.Body.Close()
   268  
   269  	t.Logf("%s", body)
   270  	cs := ChannelStatsDoc{}
   271  	err = json.Unmarshal(body, &cs)
   272  	test.Nil(t, err)
   273  	test.Equal(t, topicName, cs.TopicName)
   274  	test.Equal(t, "ch", cs.ChannelName)
   275  	test.Equal(t, 0, int(cs.Depth))
   276  	test.Equal(t, 0, int(cs.MemoryDepth))
   277  	test.Equal(t, 0, int(cs.BackendDepth))
   278  	test.Equal(t, 0, int(cs.MessageCount))
   279  	test.Equal(t, false, cs.Paused)
   280  	test.Equal(t, 0, int(cs.InFlightCount))
   281  	test.Equal(t, 0, int(cs.DeferredCount))
   282  	test.Equal(t, 0, int(cs.RequeueCount))
   283  	test.Equal(t, 0, int(cs.TimeoutCount))
   284  	test.Equal(t, 0, len(cs.Clients))
   285  }
   286  
   287  func TestHTTPNodesSingleGET(t *testing.T) {
   288  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   289  	defer os.RemoveAll(dataPath)
   290  	defer nsqds[0].Exit()
   291  	defer nsqlookupds[0].Exit()
   292  	defer nsqadmin1.Exit()
   293  
   294  	topicName := "test_nodes_single_get" + strconv.Itoa(int(time.Now().Unix()))
   295  	topic := nsqds[0].GetTopic(topicName)
   296  	topic.GetChannel("ch")
   297  	time.Sleep(100 * time.Millisecond)
   298  
   299  	client := http.Client{}
   300  	url := fmt.Sprintf("http://%s/api/nodes/%s", nsqadmin1.RealHTTPAddr(),
   301  		nsqds[0].RealHTTPAddr().String())
   302  	req, _ := http.NewRequest("GET", url, nil)
   303  	resp, err := client.Do(req)
   304  	test.Nil(t, err)
   305  	test.Equal(t, 200, resp.StatusCode)
   306  	body, _ := io.ReadAll(resp.Body)
   307  	resp.Body.Close()
   308  
   309  	t.Logf("%s", body)
   310  	ns := NodeStatsDoc{}
   311  	err = json.Unmarshal(body, &ns)
   312  	test.Nil(t, err)
   313  	test.Equal(t, nsqds[0].RealHTTPAddr().String(), ns.Node)
   314  	test.Equal(t, 1, len(ns.TopicStats))
   315  	testTopic := ns.TopicStats[0]
   316  	test.Equal(t, topicName, testTopic.TopicName)
   317  	test.Equal(t, 0, int(testTopic.Depth))
   318  	test.Equal(t, 0, int(testTopic.MemoryDepth))
   319  	test.Equal(t, 0, int(testTopic.BackendDepth))
   320  	test.Equal(t, 0, int(testTopic.MessageCount))
   321  	test.Equal(t, false, testTopic.Paused)
   322  }
   323  
   324  func TestHTTPCreateTopicPOST(t *testing.T) {
   325  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   326  	defer os.RemoveAll(dataPath)
   327  	defer nsqds[0].Exit()
   328  	defer nsqlookupds[0].Exit()
   329  	defer nsqadmin1.Exit()
   330  
   331  	time.Sleep(100 * time.Millisecond)
   332  
   333  	topicName := "test_create_topic_post" + strconv.Itoa(int(time.Now().Unix()))
   334  
   335  	client := http.Client{}
   336  	url := fmt.Sprintf("http://%s/api/topics", nsqadmin1.RealHTTPAddr())
   337  	body, _ := json.Marshal(map[string]interface{}{
   338  		"topic": topicName,
   339  	})
   340  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   341  	resp, err := client.Do(req)
   342  	test.Nil(t, err)
   343  	test.Equal(t, 200, resp.StatusCode)
   344  	resp.Body.Close()
   345  }
   346  
   347  func TestHTTPCreateTopicChannelPOST(t *testing.T) {
   348  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   349  	defer os.RemoveAll(dataPath)
   350  	defer nsqds[0].Exit()
   351  	defer nsqlookupds[0].Exit()
   352  	defer nsqadmin1.Exit()
   353  
   354  	time.Sleep(100 * time.Millisecond)
   355  
   356  	topicName := "test_create_topic_channel_post" + strconv.Itoa(int(time.Now().Unix()))
   357  
   358  	client := http.Client{}
   359  	url := fmt.Sprintf("http://%s/api/topics", nsqadmin1.RealHTTPAddr())
   360  	body, _ := json.Marshal(map[string]interface{}{
   361  		"topic":   topicName,
   362  		"channel": "ch",
   363  	})
   364  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   365  	resp, err := client.Do(req)
   366  	test.Nil(t, err)
   367  	test.Equal(t, 200, resp.StatusCode)
   368  	resp.Body.Close()
   369  }
   370  
   371  func TestHTTPTombstoneTopicNodePOST(t *testing.T) {
   372  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   373  	defer os.RemoveAll(dataPath)
   374  	defer nsqds[0].Exit()
   375  	defer nsqlookupds[0].Exit()
   376  	defer nsqadmin1.Exit()
   377  
   378  	topicName := "test_tombstone_topic_node_post" + strconv.Itoa(int(time.Now().Unix()))
   379  	nsqds[0].GetTopic(topicName)
   380  	time.Sleep(100 * time.Millisecond)
   381  
   382  	client := http.Client{}
   383  	url := fmt.Sprintf("http://%s/api/nodes/%s", nsqadmin1.RealHTTPAddr(), nsqds[0].RealHTTPAddr())
   384  	body, _ := json.Marshal(map[string]interface{}{
   385  		"topic": topicName,
   386  	})
   387  	req, _ := http.NewRequest("DELETE", url, bytes.NewBuffer(body))
   388  	resp, err := client.Do(req)
   389  	test.Nil(t, err)
   390  	test.Equal(t, 200, resp.StatusCode)
   391  	resp.Body.Close()
   392  }
   393  
   394  func TestHTTPDeleteTopicPOST(t *testing.T) {
   395  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   396  	defer os.RemoveAll(dataPath)
   397  	defer nsqds[0].Exit()
   398  	defer nsqlookupds[0].Exit()
   399  	defer nsqadmin1.Exit()
   400  
   401  	topicName := "test_delete_topic_post" + strconv.Itoa(int(time.Now().Unix()))
   402  	nsqds[0].GetTopic(topicName)
   403  	time.Sleep(100 * time.Millisecond)
   404  
   405  	client := http.Client{}
   406  	url := fmt.Sprintf("http://%s/api/topics/%s", nsqadmin1.RealHTTPAddr(), topicName)
   407  	req, _ := http.NewRequest("DELETE", url, nil)
   408  	resp, err := client.Do(req)
   409  	test.Nil(t, err)
   410  	test.Equal(t, 200, resp.StatusCode)
   411  	resp.Body.Close()
   412  }
   413  
   414  func TestHTTPDeleteChannelPOST(t *testing.T) {
   415  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   416  	defer os.RemoveAll(dataPath)
   417  	defer nsqds[0].Exit()
   418  	defer nsqlookupds[0].Exit()
   419  	defer nsqadmin1.Exit()
   420  
   421  	topicName := "test_delete_channel_post" + strconv.Itoa(int(time.Now().Unix()))
   422  	topic := nsqds[0].GetTopic(topicName)
   423  	topic.GetChannel("ch")
   424  	time.Sleep(100 * time.Millisecond)
   425  
   426  	client := http.Client{}
   427  	url := fmt.Sprintf("http://%s/api/topics/%s/ch", nsqadmin1.RealHTTPAddr(), topicName)
   428  	req, _ := http.NewRequest("DELETE", url, nil)
   429  	resp, err := client.Do(req)
   430  	test.Nil(t, err)
   431  	test.Equal(t, 200, resp.StatusCode)
   432  	resp.Body.Close()
   433  }
   434  
   435  func TestHTTPPauseTopicPOST(t *testing.T) {
   436  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   437  	defer os.RemoveAll(dataPath)
   438  	defer nsqds[0].Exit()
   439  	defer nsqlookupds[0].Exit()
   440  	defer nsqadmin1.Exit()
   441  
   442  	topicName := "test_pause_topic_post" + strconv.Itoa(int(time.Now().Unix()))
   443  	nsqds[0].GetTopic(topicName)
   444  	time.Sleep(100 * time.Millisecond)
   445  
   446  	client := http.Client{}
   447  	url := fmt.Sprintf("http://%s/api/topics/%s", nsqadmin1.RealHTTPAddr(), topicName)
   448  	body, _ := json.Marshal(map[string]interface{}{
   449  		"action": "pause",
   450  	})
   451  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   452  	resp, err := client.Do(req)
   453  	test.Nil(t, err)
   454  	_, _ = io.ReadAll(resp.Body)
   455  	test.Equal(t, 200, resp.StatusCode)
   456  	resp.Body.Close()
   457  
   458  	url = fmt.Sprintf("http://%s/api/topics/%s", nsqadmin1.RealHTTPAddr(), topicName)
   459  	body, _ = json.Marshal(map[string]interface{}{
   460  		"action": "unpause",
   461  	})
   462  	req, _ = http.NewRequest("POST", url, bytes.NewBuffer(body))
   463  	resp, err = client.Do(req)
   464  	test.Nil(t, err)
   465  	test.Equal(t, 200, resp.StatusCode)
   466  	resp.Body.Close()
   467  }
   468  
   469  func TestHTTPPauseChannelPOST(t *testing.T) {
   470  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   471  	defer os.RemoveAll(dataPath)
   472  	defer nsqds[0].Exit()
   473  	defer nsqlookupds[0].Exit()
   474  	defer nsqadmin1.Exit()
   475  
   476  	topicName := "test_pause_channel_post" + strconv.Itoa(int(time.Now().Unix()))
   477  	topic := nsqds[0].GetTopic(topicName)
   478  	topic.GetChannel("ch")
   479  	time.Sleep(100 * time.Millisecond)
   480  
   481  	client := http.Client{}
   482  	url := fmt.Sprintf("http://%s/api/topics/%s/ch", nsqadmin1.RealHTTPAddr(), topicName)
   483  	body, _ := json.Marshal(map[string]interface{}{
   484  		"action": "pause",
   485  	})
   486  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   487  	resp, err := client.Do(req)
   488  	test.Nil(t, err)
   489  	_, _ = io.ReadAll(resp.Body)
   490  	test.Equal(t, 200, resp.StatusCode)
   491  	resp.Body.Close()
   492  
   493  	url = fmt.Sprintf("http://%s/api/topics/%s/ch", nsqadmin1.RealHTTPAddr(), topicName)
   494  	body, _ = json.Marshal(map[string]interface{}{
   495  		"action": "unpause",
   496  	})
   497  	req, _ = http.NewRequest("POST", url, bytes.NewBuffer(body))
   498  	resp, err = client.Do(req)
   499  	test.Nil(t, err)
   500  	test.Equal(t, 200, resp.StatusCode)
   501  	resp.Body.Close()
   502  }
   503  
   504  func TestHTTPEmptyTopicPOST(t *testing.T) {
   505  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   506  	defer os.RemoveAll(dataPath)
   507  	defer nsqds[0].Exit()
   508  	defer nsqlookupds[0].Exit()
   509  	defer nsqadmin1.Exit()
   510  
   511  	topicName := "test_empty_topic_post" + strconv.Itoa(int(time.Now().Unix()))
   512  	topic := nsqds[0].GetTopic(topicName)
   513  	topic.PutMessage(nsqd.NewMessage(nsqd.MessageID{}, []byte("1234")))
   514  	test.Equal(t, int64(1), topic.Depth())
   515  	time.Sleep(100 * time.Millisecond)
   516  
   517  	client := http.Client{}
   518  	url := fmt.Sprintf("http://%s/api/topics/%s", nsqadmin1.RealHTTPAddr(), topicName)
   519  	body, _ := json.Marshal(map[string]interface{}{
   520  		"action": "empty",
   521  	})
   522  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   523  	resp, err := client.Do(req)
   524  	test.Nil(t, err)
   525  	_, _ = io.ReadAll(resp.Body)
   526  	test.Equal(t, 200, resp.StatusCode)
   527  	resp.Body.Close()
   528  
   529  	test.Equal(t, int64(0), topic.Depth())
   530  }
   531  
   532  func TestHTTPEmptyChannelPOST(t *testing.T) {
   533  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   534  	defer os.RemoveAll(dataPath)
   535  	defer nsqds[0].Exit()
   536  	defer nsqlookupds[0].Exit()
   537  	defer nsqadmin1.Exit()
   538  
   539  	topicName := "test_empty_channel_post" + strconv.Itoa(int(time.Now().Unix()))
   540  	topic := nsqds[0].GetTopic(topicName)
   541  	channel := topic.GetChannel("ch")
   542  	channel.PutMessage(nsqd.NewMessage(nsqd.MessageID{}, []byte("1234")))
   543  
   544  	time.Sleep(100 * time.Millisecond)
   545  	test.Equal(t, int64(1), channel.Depth())
   546  
   547  	client := http.Client{}
   548  	url := fmt.Sprintf("http://%s/api/topics/%s/ch", nsqadmin1.RealHTTPAddr(), topicName)
   549  	body, _ := json.Marshal(map[string]interface{}{
   550  		"action": "empty",
   551  	})
   552  	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
   553  	resp, err := client.Do(req)
   554  	test.Nil(t, err)
   555  	_, _ = io.ReadAll(resp.Body)
   556  	test.Equal(t, 200, resp.StatusCode)
   557  	resp.Body.Close()
   558  
   559  	test.Equal(t, int64(0), channel.Depth())
   560  }
   561  
   562  func TestHTTPconfig(t *testing.T) {
   563  	dataPath, nsqds, nsqlookupds, nsqadmin1 := bootstrapNSQCluster(t)
   564  	defer os.RemoveAll(dataPath)
   565  	defer nsqds[0].Exit()
   566  	defer nsqlookupds[0].Exit()
   567  	defer nsqadmin1.Exit()
   568  
   569  	lopts := nsqlookupd.NewOptions()
   570  	lopts.Logger = test.NewTestLogger(t)
   571  
   572  	lopts1 := *lopts
   573  	_, _, lookupd1 := mustStartNSQLookupd(&lopts1)
   574  	defer lookupd1.Exit()
   575  	lopts2 := *lopts
   576  	_, _, lookupd2 := mustStartNSQLookupd(&lopts2)
   577  	defer lookupd2.Exit()
   578  
   579  	url := fmt.Sprintf("http://%s/config/nsqlookupd_http_addresses", nsqadmin1.RealHTTPAddr())
   580  	resp, err := http.Get(url)
   581  	test.Nil(t, err)
   582  	defer resp.Body.Close()
   583  	body, _ := io.ReadAll(resp.Body)
   584  	test.Equal(t, 200, resp.StatusCode)
   585  	origaddrs := fmt.Sprintf(`["%s"]`, nsqlookupds[0].RealHTTPAddr().String())
   586  	test.Equal(t, origaddrs, string(body))
   587  
   588  	client := http.Client{}
   589  	addrs := fmt.Sprintf(`["%s","%s"]`, lookupd1.RealHTTPAddr().String(), lookupd2.RealHTTPAddr().String())
   590  	url = fmt.Sprintf("http://%s/config/nsqlookupd_http_addresses", nsqadmin1.RealHTTPAddr())
   591  	req, err := http.NewRequest("PUT", url, bytes.NewBuffer([]byte(addrs)))
   592  	test.Nil(t, err)
   593  	resp, err = client.Do(req)
   594  	test.Nil(t, err)
   595  	defer resp.Body.Close()
   596  	body, _ = io.ReadAll(resp.Body)
   597  	test.Equal(t, 200, resp.StatusCode)
   598  	test.Equal(t, addrs, string(body))
   599  
   600  	url = fmt.Sprintf("http://%s/config/log_level", nsqadmin1.RealHTTPAddr())
   601  	req, err = http.NewRequest("PUT", url, bytes.NewBuffer([]byte(`fatal`)))
   602  	test.Nil(t, err)
   603  	resp, err = client.Do(req)
   604  	test.Nil(t, err)
   605  	defer resp.Body.Close()
   606  	_, _ = io.ReadAll(resp.Body)
   607  	test.Equal(t, 200, resp.StatusCode)
   608  	test.Equal(t, LOG_FATAL, nsqadmin1.getOpts().LogLevel)
   609  
   610  	url = fmt.Sprintf("http://%s/config/log_level", nsqadmin1.RealHTTPAddr())
   611  	req, err = http.NewRequest("PUT", url, bytes.NewBuffer([]byte(`bad`)))
   612  	test.Nil(t, err)
   613  	resp, err = client.Do(req)
   614  	test.Nil(t, err)
   615  	defer resp.Body.Close()
   616  	_, _ = io.ReadAll(resp.Body)
   617  	test.Equal(t, 400, resp.StatusCode)
   618  }
   619  
   620  func TestHTTPconfigCIDR(t *testing.T) {
   621  	opts := NewOptions()
   622  	opts.HTTPAddress = "127.0.0.1:0"
   623  	opts.NSQLookupdHTTPAddresses = []string{"127.0.0.1:4161"}
   624  	opts.Logger = test.NewTestLogger(t)
   625  	opts.AllowConfigFromCIDR = "10.0.0.0/8"
   626  	nsqadmin, err := New(opts)
   627  	test.Nil(t, err)
   628  	go func() {
   629  		err := nsqadmin.Main()
   630  		if err != nil {
   631  			panic(err)
   632  		}
   633  	}()
   634  	defer nsqadmin.Exit()
   635  
   636  	time.Sleep(100 * time.Millisecond)
   637  
   638  	url := fmt.Sprintf("http://%s/config/nsqlookupd_http_addresses", nsqadmin.RealHTTPAddr())
   639  	resp, err := http.Get(url)
   640  	test.Nil(t, err)
   641  	defer resp.Body.Close()
   642  	_, _ = io.ReadAll(resp.Body)
   643  	test.Equal(t, 403, resp.StatusCode)
   644  }