Files
fn-serverless/api/api.go
2016-07-17 21:49:25 -07:00

206 lines
4.6 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"github.com/iron-io/iron_go/cache"
)
var icache = cache.New("routing-table")
var config *Config
func New(conf *Config) *Api {
config = conf
api := &Api{}
return api
}
type Api struct {
}
func (api *Api) Start() {
log.Infoln("Starting up router version", Version)
r := mux.NewRouter()
// dev:
s := r.PathPrefix("/api").Subrouter()
// production:
// s := r.Host("router.irondns.info").Subrouter()
// s.Handle("/1/projects/{project_id}/register", &Register{})
s.Handle("/v1/apps", &NewApp{})
s.HandleFunc("/v1/apps/{app_name}/routes", NewRoute)
s.HandleFunc("/ping", Ping)
s.HandleFunc("/version", VersionHandler)
// s.Handle("/addworker", &WorkerHandler{})
s.HandleFunc("/", Ping)
r.HandleFunc("/elb-ping-router", Ping) // for ELB health check
// for testing app responses, pass in app name, can use localhost
s4 := r.Queries("app", "").Subrouter()
// s4.HandleFunc("/appsr", Ping)
s4.HandleFunc("/{rest:.*}", Run)
s4.NotFoundHandler = http.HandlerFunc(Run)
// s3 := r.Queries("rhost", "").Subrouter()
// s3.HandleFunc("/", ProxyFunc2)
// This is where all the main incoming traffic goes
r.NotFoundHandler = http.HandlerFunc(Run)
http.Handle("/", r)
port := 8080
log.Infoln("Router started, listening and serving on port", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%v", port), nil))
}
type NewApp struct{}
// This registers a new host
func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) {
log.Println("NewApp called!")
vars := mux.Vars(req)
projectId := vars["project_id"]
// token := common.GetToken(req)
log.Infoln("project_id:", projectId)
app := App{}
if !ReadJSON(w, req, &app) {
return
}
log.Infoln("body read into app:", app)
app.ProjectId = projectId
_, err := getApp(app.Name)
if err == nil {
SendError(w, 400, fmt.Sprintln("An app with this name already exists.", err))
return
}
app.Routes = make(map[string]*Route3)
// create dns entry
// TODO: Add project id to this. eg: appname.projectid.iron.computer
log.Debug("Creating dns entry.")
regOk := registerHost(w, req, &app)
if !regOk {
return
}
// todo: do we need to close body?
err = putApp(&app)
if err != nil {
log.Infoln("couldn't create app:", err)
SendError(w, 400, fmt.Sprintln("Could not create app!", err))
return
}
log.Infoln("registered app:", app)
v := map[string]interface{}{"app": app, "msg": "App created successfully."}
SendSuccess(w, "App created successfully.", v)
}
func NewRoute(w http.ResponseWriter, req *http.Request) {
fmt.Println("NewRoute")
vars := mux.Vars(req)
projectId := vars["project_id"]
appName := vars["app_name"]
log.Infoln("project_id: ", projectId, "app: ", appName)
route := &Route3{}
if !ReadJSON(w, req, &route) {
return
}
log.Infoln("body read into route:", route)
// TODO: validate route
app, err := getApp(appName)
if err != nil {
SendError(w, 400, fmt.Sprintln("This app does not exist. Please create app first.", err))
return
}
if route.Type == "" {
route.Type = "run"
}
// app.Routes = append(app.Routes, route)
app.Routes[route.Path] = route
err = putApp(app)
if err != nil {
log.Errorln("Couldn't create route!:", err)
SendError(w, 400, fmt.Sprintln("Could not create route!", err))
return
}
log.Infoln("Route created:", route)
v := map[string]interface{}{"url": fmt.Sprintf("http://%v%v", app.Dns, route.Path), "msg": "Route created successfully."}
SendSuccess(w, "Route created successfully.", v)
}
func getRoute(host string) (*Route, error) {
log.Infoln("getRoute for host:", host)
rx, err := icache.Get(host)
if err != nil {
return nil, err
}
rx2 := []byte(rx.(string))
route := Route{}
err = json.Unmarshal(rx2, &route)
if err != nil {
return nil, err
}
return &route, err
}
func putRoute(route *Route) error {
item := cache.Item{}
v, err := json.Marshal(route)
if err != nil {
return err
}
item.Value = string(v)
err = icache.Put(route.Host, &item)
return err
}
func getApp(name string) (*App, error) {
log.Infoln("getapp:", name)
rx, err := icache.Get(name)
if err != nil {
return nil, err
}
rx2 := []byte(rx.(string))
app := App{}
err = json.Unmarshal(rx2, &app)
if err != nil {
return nil, err
}
return &app, err
}
func putApp(app *App) error {
item := cache.Item{}
v, err := json.Marshal(app)
if err != nil {
return err
}
item.Value = string(v)
err = icache.Put(app.Name, &item)
return err
}
func Ping(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, "pong")
}
func VersionHandler(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, Version)
}