---
# System prepended metadata

title: parse

---

# parse

```go=
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

var (
	port      = flag.String("port", "8080", "port")
	whatsup   = flag.String("api", "http://whatsup-test.dev001.wise-paas.com", "api URL")
	emptyData = Data{
		DeviceName:  "-",
		PollTimeUtc: "1970-01-01T00:00:00Z",
		ID:          "-",
	}
	emptySeries = Series{
		PollTimeUtc: "1970-01-01T00:00:00Z",
	}
)

func main() {
	flag.Parse()
	fmt.Println(*port)
	fmt.Println(*whatsup)

	http.HandleFunc("/", handler)
	http.HandleFunc("/api/v1/devices/", deviceHandler)
	http.ListenAndServe(":"+*port, nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(time.Now(), r.URL.Path)
	token := r.Header.Get("Authorization")

	bytesBody, statusCode, err := call(r.Method, r.URL.Path, r.URL.RawQuery, token, r.Body)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
	w.Write(bytesBody)

	return
}

func deviceHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(time.Now(), r.URL.Path)
	token := r.Header.Get("Authorization")
	w.Header().Set("Content-Type", "application/json")
	bytesBody, statusCode, err := call(r.Method, r.URL.Path, r.URL.RawQuery, token, r.Body)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		return
	}

	if statusCode > 299 {
		w.WriteHeader(statusCode)
		w.Write(bytesBody)
		return
	}

	switch {
	case strings.HasSuffix(r.URL.Path, "/cpu-utilization"):
		result, err := cpuJson(bytesBody)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(err.Error()))
			return
		}
		w.WriteHeader(statusCode)
		w.Write(result)
		return

	case strings.HasSuffix(r.URL.Path, "/memory-utilization"):
		result, err := memoryJson(bytesBody)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(err.Error()))
			return
		}
		w.WriteHeader(statusCode)
		w.Write(result)
		return

	case strings.HasSuffix(r.URL.Path, "/disk-utilization"):
		result, err := diskJson(bytesBody)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(err.Error()))
			return
		}
		w.WriteHeader(statusCode)
		w.Write(result)
		return

	default:
		w.WriteHeader(statusCode)
		w.Write(bytesBody)
		return
	}
}

func call(method, path, rawQuery, token string, reqBody io.ReadCloser) ([]byte, int, error) {
	split := strings.Split(*whatsup, "://")
	if len(split) != 2 {
		return nil, http.StatusInternalServerError, fmt.Errorf("invalid url")
	}

	url := url.URL{
		Scheme:   split[0],
		Host:     split[1],
		Path:     path,
		RawQuery: rawQuery,
	}

	client := &http.Client{
		Timeout:   30 * time.Second,
		Transport: &http.Transport{DisableKeepAlives: true, DisableCompression: true,},
	}
	req, err := http.NewRequest(method, url.String(), reqBody)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}

	setHeader(req, token)

	res, err := client.Do(req)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}

	if res == nil {
		return nil, http.StatusInternalServerError, fmt.Errorf("no response.")
	}

	defer res.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, http.StatusInternalServerError, err
	}

	return body, res.StatusCode, nil
}

func setHeader(req *http.Request, token string) {
	req.Header.Set("Authorization", token)
	req.Header.Set("Content-Type", "application/json")
}

func cpuJson(bytesBody []byte) ([]byte, error) {
	var cpuStruct CpuUtilization
	if err := json.Unmarshal(bytesBody, &cpuStruct); err != nil {
		return nil, err
	}

	if cpuStruct.Data == nil || len(cpuStruct.Data) == 0 {
		cpuStruct.Data = []CpuData{{
			Series: []CpuSeries{{
				CpuID:  "-",
				ID:     "-",
				Series: emptySeries,
			}},
			CpuID: "-",
			Cpu:   "-",
			Data:  emptyData,
		}}
		result, err := json.Marshal(cpuStruct)
		if err != nil {
			return nil, err
		}

		return result, nil
	}

	for i := 0; i < len(cpuStruct.Data); i++ {
		if cpuStruct.Data[i].Series == nil || len(cpuStruct.Data[i].Series) == 0 {
			cpuStruct.Data[i].Series = []CpuSeries{{
				CpuID:  "-",
				ID:     "-",
				Series: emptySeries,
			}}
			continue
		}
		for j := 0; j < len(cpuStruct.Data[i].Series); j++ {
			cpuStruct.Data[i].Series[j].CpuID = cpuStruct.Data[i].CpuID
			cpuStruct.Data[i].Series[j].ID = cpuStruct.Data[i].ID
		}
	}

	result, err := json.Marshal(cpuStruct)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func memoryJson(bytesBody []byte) ([]byte, error) {
	var memStruct MemoryUtilization
	if err := json.Unmarshal(bytesBody, &memStruct); err != nil {
		return nil, err
	}

	if memStruct.Data == nil || len(memStruct.Data) == 0 {
		memStruct.Data = []MemoryData{{
			Series: []MemorySeries{{
				MemoryID: "-",
				ID:       "-",
				Series:   emptySeries,
			}},
			MemoryID: "-",
			Memory:   "-",
			Data:     emptyData,
		}}
		result, err := json.Marshal(memStruct)
		if err != nil {
			return nil, err
		}

		return result, nil
	}

	for i := 0; i < len(memStruct.Data); i++ {
		if memStruct.Data[i].Series == nil || len(memStruct.Data[i].Series) == 0 {
			memStruct.Data[i].Series = []MemorySeries{{
				MemoryID: "-",
				ID:       "-",
				Series:   emptySeries,
			},
			}
			continue
		}
		for j := 0; j < len(memStruct.Data[i].Series); j++ {
			memStruct.Data[i].Series[j].MemoryID = memStruct.Data[i].MemoryID
			memStruct.Data[i].Series[j].ID = memStruct.Data[i].ID
		}
	}

	result, err := json.Marshal(memStruct)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func diskJson(bytesBody []byte) ([]byte, error) {
	var diskStruct DiskUtilization
	if err := json.Unmarshal(bytesBody, &diskStruct); err != nil {
		return nil, err
	}

	if diskStruct.Data == nil || len(diskStruct.Data) == 0 {
		diskStruct.Data = []DiskData{{
			Series: []DiskSeries{{
				DiskID: "-",
				ID:     "-",
				Series: emptySeries,
			}},
			DiskID: "-",
			Disk:   "-",
			Data:   emptyData,
		}}
		result, err := json.Marshal(diskStruct)
		if err != nil {
			return nil, err
		}

		return result, nil
	}

	for i := 0; i < len(diskStruct.Data); i++ {
		if diskStruct.Data[i].Series == nil || len(diskStruct.Data[i].Series) == 0 {
			diskStruct.Data[i].Series = []DiskSeries{{
				DiskID: "-",
				ID:     "-",
				Series: emptySeries,
			},
			}
			continue
		}
		for j := 0; j < len(diskStruct.Data[i].Series); j++ {
			diskStruct.Data[i].Series[j].DiskID = diskStruct.Data[i].DiskID
			diskStruct.Data[i].Series[j].ID = diskStruct.Data[i].ID
		}
	}

	result, err := json.Marshal(diskStruct)
	if err != nil {
		return nil, err
	}

	return result, nil
}

type CpuUtilization struct {
	Paging Paging    `json:"paging"`
	Data   []CpuData `json:"data"`
}

type MemoryUtilization struct {
	Paging Paging       `json:"paging"`
	Data   []MemoryData `json:"data"`
}

type DiskUtilization struct {
	Paging Paging     `json:"paging"`
	Data   []DiskData `json:"data"`
}

type Paging struct {
	PageID string `json:"pageId"`
	Size   int    `json:"size"`
}

type CpuData struct {
	Cpu    string      `json:"cpu"`
	CpuID  string      `json:"cpuId"`
	Series []CpuSeries `json:"series"`
	Data
}

type MemoryData struct {
	Memory   string         `json:"memory"`
	MemoryID string         `json:"memoryId"`
	Series   []MemorySeries `json:"series"`
	Data
}

type DiskData struct {
	Disk   string       `json:"disk"`
	DiskID string       `json:"diskId"`
	Series []DiskSeries `json:"series"`
	Data
}

type Data struct {
	DeviceName              string  `json:"deviceName"`
	PollTimeUtc             string  `json:"pollTimeUtc"`
	TimeFromLastPollSeconds int     `json:"timeFromLastPollSeconds"`
	Size                    float64 `json:"size"`
	MinUsed                 float64 `json:"minUsed"`
	MaxUsed                 float64 `json:"maxUsed"`
	AvgUsed                 float64 `json:"avgUsed"`
	MinPercent              float64 `json:"minPercent"`
	MaxPercent              float64 `json:"maxPercent"`
	AvgPercent              float64 `json:"avgPercent"`
	ID                      string  `json:"id"`
}

type CpuSeries struct {
	CpuID string `json:"cpuId"`
	ID    string `json:"id"`
	Series
}

type MemorySeries struct {
	MemoryID string `json:"memoryId"`
	ID       string `json:"id"`
	Series
}

type DiskSeries struct {
	DiskID string `json:"diskId"`
	ID     string `json:"id"`
	Series
}

type Series struct {
	PollTimeUtc string  `json:"pollTimeUtc"`
	AvgPercent  float64 `json:"avgPercent"`
	MinPercent  float64 `json:"minPercent"`
	MaxPercent  float64 `json:"maxPercent"`
}

```