diff --git a/server/jetstream_api.go b/server/jetstream_api.go index 32773443..28170294 100644 --- a/server/jetstream_api.go +++ b/server/jetstream_api.go @@ -952,7 +952,14 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, subject, repl s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: mset.Config()} + config := mset.Config() + // MQTT streams are created without subject, but "nats" tooling would then + // fail to display them since it uses validation and expect the config's + // Subjects to not be empty. + if strings.HasPrefix(name, mqttStreamNamePrefix) && len(config.Subjects) == 0 { + config.Subjects = []string{">"} + } + resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: config} s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) } diff --git a/server/mqtt_test.go b/server/mqtt_test.go index 7427cf9f..7c76b490 100644 --- a/server/mqtt_test.go +++ b/server/mqtt_test.go @@ -3745,7 +3745,48 @@ func TestMQTTConfigReload(t *testing.T) { testMQTTCheckPubMsgNoAck(t, c, r, "foo", mqttPubQos1, []byte("msg2")) } +func TestMQTTStreamInfoReturnsNonEmptySubject(t *testing.T) { + o := testMQTTDefaultOptions() + s := testMQTTRunServer(t, o) + defer s.Shutdown() + + cisub := &mqttConnInfo{clientID: "sub", cleanSess: false} + c, r := testMQTTConnect(t, cisub, o.MQTT.Host, o.MQTT.Port) + defer c.Close() + testMQTTCheckConnAck(t, r, mqttConnAckRCConnectionAccepted, false) + + nc := natsConnect(t, s.ClientURL()) + defer nc.Close() + + // Check that we can query all MQTT streams. MQTT streams are + // created without subject filter, however, if we return them like this, + // the 'nats' utility will fail to display them due to some xml validation. + for _, sname := range []string{ + mqttStreamName, + mqttSessionsStreamName, + mqttRetainedMsgsStreamName, + } { + t.Run(sname, func(t *testing.T) { + resp, err := nc.Request(fmt.Sprintf(JSApiStreamInfoT, sname), nil, time.Second) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + var bResp JSApiStreamInfoResponse + if err = json.Unmarshal(resp.Data, &bResp); err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if len(bResp.Config.Subjects) == 0 { + t.Fatalf("No subject returned, which will cause nats tooling to fail: %+v", bResp.Config) + } + }) + } +} + +////////////////////////////////////////////////////////////////////////// +// // Benchmarks +// +////////////////////////////////////////////////////////////////////////// const ( mqttPubSubj = "a"