1package main
2
3import (
4	"encoding/json"
5	"fmt"
6	"net/http"
7)
8
9type Response struct {
10	PathExpression string   `yaml:"pathExpression"`
11	Data           []Metric `yaml:"data"`
12}
13
14type Metric struct {
15	MetricName string    `yaml:"metricName"`
16	Step       int       `yaml:"step"`
17	StartTime  int       `yaml:"startTime"`
18	Values     []float64 `yaml:"values"`
19}
20
21type metricForJson struct {
22	MetricName string
23	Values     []string
24}
25
26func (m *Metric) MarshalJSON() ([]byte, error) {
27	m2 := metricForJson{
28		MetricName: m.MetricName,
29		Values:     make([]string, len(m.Values)),
30	}
31
32	for i, v := range m.Values {
33		m2.Values[i] = fmt.Sprintf("%v", v)
34	}
35
36	return json.Marshal(m2)
37}
38
39type responseFormat int
40
41const (
42	jsonFormat responseFormat = iota
43	pickleFormat
44	protoV2Format
45	protoV3Format
46)
47
48func getFormat(req *http.Request) (responseFormat, error) {
49	format := req.FormValue("format")
50	if format == "" {
51		format = "json"
52	}
53
54	formatCode, ok := knownFormats[format]
55	if !ok {
56		return formatCode, fmt.Errorf("unknown format")
57	}
58
59	return formatCode, nil
60}
61
62var knownFormats = map[string]responseFormat{
63	"json":            jsonFormat,
64	"pickle":          pickleFormat,
65	"protobuf":        protoV2Format,
66	"protobuf3":       protoV2Format,
67	"carbonapi_v2_pb": protoV2Format,
68	"carbonapi_v3_pb": protoV3Format,
69}
70
71func (r responseFormat) String() string {
72	switch r {
73	case jsonFormat:
74		return "json"
75	case pickleFormat:
76		return "pickle"
77	case protoV2Format:
78		return "carbonapi_v2_pb"
79	default:
80		return "unknown"
81	}
82}
83
84func copyResponse(src Response) Response {
85	dst := Response{
86		PathExpression: src.PathExpression,
87		Data:           make([]Metric, len(src.Data)),
88	}
89
90	for i := range src.Data {
91		dst.Data[i] = Metric{
92			MetricName: src.Data[i].MetricName,
93			Values:     make([]float64, len(src.Data[i].Values)),
94			StartTime:  src.Data[i].StartTime,
95			Step:       src.Data[i].Step,
96		}
97
98		for j := range src.Data[i].Values {
99			dst.Data[i].Values[j] = src.Data[i].Values[j]
100		}
101	}
102
103	return dst
104}
105
106func copyMap(src map[string]Response) map[string]Response {
107	dst := make(map[string]Response)
108
109	for k, v := range src {
110		dst[k] = copyResponse(v)
111	}
112
113	return dst
114}
115
116const (
117	contentTypeJSON       = "application/json"
118	contentTypeProtobuf   = "application/x-protobuf"
119	contentTypeJavaScript = "text/javascript"
120	contentTypeRaw        = "text/plain"
121	contentTypePickle     = "application/pickle"
122	contentTypePNG        = "image/png"
123	contentTypeCSV        = "text/csv"
124	contentTypeSVG        = "image/svg+xml"
125)
126