grafana/pkg/plugins/httpresponsesender/http_response_sender.go
Marcus Efraimsson 4cbda914bd
Plugins: Refactor call resource API handling (#67234)
Moving call resource API stream handling within plugin management as a utility/wrapper. 

Closes #66889

Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
2023-04-28 14:02:27 +02:00

66 lines
1.5 KiB
Go

package httpresponsesender
import (
"errors"
"fmt"
"net/http"
"net/textproto"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
// HTTPResponseSender implements backend.CallResourceResponseSender and
// writes an HTTP response using an http.ResponseWriter given received
// backend.CallResourceResponse(s).
type HTTPResponseSender struct {
processedStreams int
w http.ResponseWriter
}
// New creates a new HTTPResponseSender.
func New(w http.ResponseWriter) *HTTPResponseSender {
if w == nil {
panic("response writer cannot be nil")
}
return &HTTPResponseSender{
w: w,
}
}
func (s *HTTPResponseSender) Send(resp *backend.CallResourceResponse) error {
if resp == nil {
return errors.New("resp cannot be nil")
}
// Expected that headers and status are only part of first stream
if s.processedStreams == 0 {
for k, values := range resp.Headers {
// Convert the keys to the canonical format of MIME headers.
// This ensures that we can safely add/overwrite headers
// even if the plugin returns them in non-canonical format
// and be sure they won't be present multiple times in the response.
k = textproto.CanonicalMIMEHeaderKey(k)
for _, v := range values {
s.w.Header().Add(k, v)
}
}
s.w.WriteHeader(resp.Status)
}
if _, err := s.w.Write(resp.Body); err != nil {
return fmt.Errorf("failed to write resource response: %v", err)
}
if flusher, ok := s.w.(http.Flusher); ok {
flusher.Flush()
}
s.processedStreams++
return nil
}
var _ backend.CallResourceResponseSender = &HTTPResponseSender{}