Example #1
0
// getResource is the function that handles the GET /resources/:resourceID route.
func getResource(c siesta.Context, w http.ResponseWriter, r *http.Request) {
	// Context variables
	requestID := c.Get("request-id").(string)
	db := c.Get("db").(*DB)
	user := c.Get("user").(string)

	// Check parameters
	var params siesta.Params
	resourceID := params.Int("resourceID", -1, "Resource identifier")
	err := params.Parse(r.Form)
	if err != nil {
		log.Printf("[Req %s] %v", requestID, err)
		c.Set("error", err.Error())
		c.Set("status-code", http.StatusBadRequest)
		return
	}

	// Make sure we have a valid resource ID.
	if *resourceID == -1 {
		c.Set("error", "invalid or missing resource ID")
		c.Set("status-code", http.StatusBadRequest)
		return
	}

	resource, err := db.resource(user, *resourceID)
	if err != nil {
		c.Set("status-code", http.StatusNotFound)
		c.Set("error", "not found")
		return
	}

	c.Set("data", resource)
}
func initSiesta() {
	h := siesta.NewService("/")
	h.Route("GET", "/", "",
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
			fmt.Fprintf(w, "Hello, World")
		})
	h.Route("GET", "/:name", "",
		func(w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			name := params.String("name", "", "")
			params.Parse(r.Form)
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
			fmt.Fprintf(w, "Hello, %s", *name)
		})
	registerHandler("siesta", h)
}
Example #3
0
func main() {
	// Create a new Service rooted at "/"
	service := siesta.NewService("/")

	// Here's a handler that uses a URL parameter.
	// Example: GET /greet/Bob
	service.Route("GET", "/greet/:name", "Greets with a name.",
		func(w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			name := params.String("name", "", "Person's name")

			err := params.Parse(r.Form)
			if err != nil {
				log.Println("Error parsing parameters!", err)
				return
			}

			fmt.Fprintf(w, "Hello, %s!", *name)
		},
	)

	// Here's a handler that uses a query string parameter.
	// Example: GET /square?number=10
	service.Route("GET", "/square", "Prints the square of a number.",
		func(w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			number := params.Int("number", 0, "A number to square")

			err := params.Parse(r.Form)
			if err != nil {
				log.Println("Error parsing parameters!", err)
				return
			}

			fmt.Fprintf(w, "%d * %d = %d.", *number, *number, (*number)*(*number))
		},
	)

	// We can also use both URL and query string parameters.
	// Example: GET /exponentiate/10?power=10
	service.Route("GET", "/exponentiate/:number", "Exponentiates a number.",
		func(w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			number := params.Float64("number", 0, "A number to exponentiate")
			power := params.Float64("power", 1, "Power")

			err := params.Parse(r.Form)
			if err != nil {
				log.Println("Error parsing parameters!", err)
				return
			}

			fmt.Fprintf(w, "%g ^ %g = %g.", *number, *power, math.Pow(*number, *power))
		},
	)

	// service is an http.Handler, so we can pass it directly to ListenAndServe.
	log.Fatal(http.ListenAndServe(":8080", service))
}
Example #4
0
func (s *APIServer) Run() {
	service := siesta.NewService("/")

	service.AddPre(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
	})

	service.AddPost(func(c siesta.Context, w http.ResponseWriter, r *http.Request, q func()) {
		resp := c.Get(responseKey)
		err, _ := c.Get(errorKey).(string)

		if resp == nil && err == "" {
			return
		}

		enc := json.NewEncoder(w)
		enc.Encode(APIResponse{
			Data:  resp,
			Error: err,
		})
	})

	service.Route("GET", "/", "Default page", func(c siesta.Context, w http.ResponseWriter, r *http.Request) {
		c.Set(responseKey, "Welcome to the Cistern API!")
	})

	service.Route("GET", "/devices", "Lists sources", func(c siesta.Context, w http.ResponseWriter, r *http.Request) {
		type ipHostname struct {
			IP       string `json:"ip"`
			Hostname string `json:"hostname,omitempty"`
		}

		devices := []ipHostname{}

		for _, dev := range s.deviceRegistry.Devices() {
			devices = append(devices, ipHostname{
				IP:       dev.IP().String(),
				Hostname: dev.Hostname(),
			})
		}

		c.Set(responseKey, devices)
	})

	service.Route("GET", "/devices/:device/metrics",
		"Lists metrics for a device",
		func(c siesta.Context, w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			device := params.String("device", "", "Device name")
			err := params.Parse(r.Form)
			if err != nil {
				c.Set(errorKey, err.Error())
				return
			}

			address := net.ParseIP(*device)
			dev, present := s.deviceRegistry.Lookup(address)
			if !present {
				c.Set(errorKey, "device not found")
				return
			}

			c.Set(responseKey, dev.Metrics())
		})

	service.Route("GET", "/devices/:device/flows",
		"Lists top flows for a device",
		func(c siesta.Context, w http.ResponseWriter, r *http.Request) {
			var params siesta.Params
			device := params.String("device", "", "Device name")
			err := params.Parse(r.Form)
			if err != nil {
				c.Set(errorKey, err.Error())
				return
			}

			address := net.ParseIP(*device)
			dev, present := s.deviceRegistry.Lookup(address)
			if !present {
				c.Set(errorKey, "device not found")
				return
			}

			type flowsResponse struct {
				ByBytes   []flows.Flow `json:"byBytes"`
				ByPackets []flows.Flow `json:"byPackets"`
			}

			topTalkers := dev.TopTalkers()
			if topTalkers == nil {
				c.Set(errorKey, "No active flows")
				return
			}

			resp := flowsResponse{
				ByBytes:   topTalkers.ByBytes(),
				ByPackets: topTalkers.ByPackets(),
			}

			c.Set(responseKey, resp)
		})

	service.Route("OPTIONS", "/series/query",
		"Accepts an OPTIONS request",
		func(w http.ResponseWriter, r *http.Request) {
			// Doesn't do anything
		})

	service.Route("POST", "/series/query",
		"Lists metrics for a device",
		s.querySeriesRoute())

	http.Handle("/", service)

	go http.ListenAndServe(s.addr, nil)
}
Example #5
0
func (s *APIServer) querySeriesRoute() func(siesta.Context, http.ResponseWriter, *http.Request) {
	return func(c siesta.Context, w http.ResponseWriter, r *http.Request) {
		var params siesta.Params
		pointWidth := params.Int64("pointWidth", 1, "Number of points to average together")
		err := params.Parse(r.Form)
		if err != nil {
			c.Set(errorKey, err.Error())
			return
		}

		var descs []queryDesc

		dec := json.NewDecoder(r.Body)
		err = dec.Decode(&descs)
		if err != nil {
			c.Set(errorKey, err.Error())
			return
		}

		now := time.Now().Unix()
		for i, desc := range descs {
			if desc.Start <= 0 {
				desc.Start += now
			}

			if desc.End <= 0 {
				desc.End += now
			}

			descs[i] = desc
		}

		resp := queryResponse{}

		for _, desc := range descs {
			log.Println(desc)
			i, err := s.seriesEngine.NewIterator(desc.Source, desc.Metric)
			if err != nil {
				log.Println(err)
				continue
			}

			err = i.Seek(desc.Start)
			if err != nil {
				log.Println(err)
				continue
			}

			s := querySeries{
				Source: desc.Source,
				Metric: desc.Metric,
				Start:  i.Point().Timestamp,
				End:    i.Point().Timestamp,
			}

			pointsSeen := 0

			currentInterval := i.Point().Timestamp / *pointWidth
			currentPoint := catena.Point{
				Timestamp: currentInterval * *pointWidth,
			}

			for {
				p := i.Point()
				if p.Timestamp > desc.End {
					break
				}

				if p.Timestamp / *pointWidth != currentInterval {
					currentPoint.Value /= float64(pointsSeen)
					s.Points = append(s.Points, currentPoint)
					currentInterval = i.Point().Timestamp / *pointWidth
					currentPoint = catena.Point{
						Timestamp: currentInterval * *pointWidth,
						Value:     p.Value,
					}
					pointsSeen = 1
					continue
				}

				currentPoint.Value += p.Value
				pointsSeen++

				err := i.Next()
				if err != nil {
					log.Println(err)
					break
				}
			}

			if pointsSeen > 0 {
				currentPoint.Value /= float64(pointsSeen)
				s.Points = append(s.Points, currentPoint)
			}
			i.Close()

			resp.Series = append(resp.Series, s)
		}

		c.Set(responseKey, resp)
	}
}