code: func (h *apiExecutor) Publish(ctx context.Context, cmd *PublishRequest) *PublishResponse {
  	defer func(started time.Time) {
  		apiCommandDurationSummary.WithLabelValues(h.protocol, "publish").Observe(time.Since(started).Seconds())
  	}(time.Now())
  
  	ch := cmd.Channel
  	data := cmd.Data
  
  	resp := &PublishResponse{}
  
  	if ch == "" {
  		h.node.Log(centrifuge.NewLogEntry(centrifuge.LogLevelError, "channel required for publish", nil))
  		resp.Error = ErrorBadRequest
  		return resp
  	}
  
  	if len(data) == 0 {
  		h.node.Log(centrifuge.NewLogEntry(centrifuge.LogLevelError, "data required for publish", nil))
  		resp.Error = ErrorBadRequest
  		return resp
  	}
  
  	_, ok := h.node.ChannelOpts(ch)
  	if !ok {
  		resp.Error = ErrorNamespaceNotFound
  		return resp
  	}
  
  	err := h.node.Publish(cmd.Channel, cmd.Data)
  	if err != nil {
  		h.node.Log(centrifuge.NewLogEntry(centrifuge.LogLevelError, "error publishing message in engine", map[string]interface{}{"error": err.Error()}))
  		resp.Error = ErrorInternal
  		return resp
  	}
  	return resp
  }
docs: // Publish publishes data into channel.