telebit/server/api_interface.go

207 lines
5.7 KiB
Go

package server
import (
"context"
"net/http"
"runtime"
"strconv"
"strings"
"github.com/gorilla/mux"
telebit "git.coolaj86.com/coolaj86/go-telebitd"
"git.coolaj86.com/coolaj86/go-telebitd/envelope"
)
const (
endPointPrefix = "/api/org.rootprojects.tunnel/"
)
var connectionTable *Table
var serverStatus *Status
var serverStatusAPI *Status
//handleAdminClient -
// - expecting an existing oneConnListener with a qualified wss client connected.
// - auth will happen again since we were just peeking at the token.
func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
serverStatus = ctx.Value(ctxServerStatus).(*Status)
connectionTable = serverStatus.ConnectionTable
serverStatusAPI = serverStatus
router := mux.NewRouter().StrictSlash(true)
router.PathPrefix("/admin/").Handler(http.StripPrefix("/admin/", http.FileServer(http.Dir("html/admin"))))
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
loginfo.Println("HandleFunc /")
serverStatus.AdminStats.IncRequests()
switch url := r.URL.Path; url {
case "/":
// check to see if we are using the administrative Host
if strings.Contains(r.Host, telebit.InvalidAdminDomain) {
http.Redirect(w, r, "/admin", 301)
serverStatus.AdminStats.IncResponses()
}
default:
http.Error(w, "Not Found", 404)
}
})
router.HandleFunc(endPointPrefix+"domains", getDomainsEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"domain/", getDomainEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"domain/{domain-name}", getDomainEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"servers", getServersEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"server/", getServerEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"server/{server-id}", getServerEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"status/", getStatusEndpoint).Methods("GET")
s := &http.Server{
Addr: ":80",
Handler: router,
}
err := s.Serve(oneConn)
if err != nil {
loginfo.Println("Serve error: ", err)
}
select {
case <-ctx.Done():
loginfo.Println("Cancel signal hit")
return
}
}
func getStatusEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
serverStatus.AdminStats.IncRequests()
statusContainer := NewStatusAPI(serverStatusAPI)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env := envelope.NewEnvelope("domains/GET")
env.Result = statusContainer
env.GenerateWriter(w)
serverStatus.AdminStats.IncResponses()
}
func getDomainsEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
serverStatus.AdminStats.IncRequests()
domainsContainer := NewDomainsAPI(connectionTable.domains)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env := envelope.NewEnvelope("domains/GET")
env.Result = domainsContainer
env.GenerateWriter(w)
serverStatus.AdminStats.IncResponses()
}
func getDomainEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
serverStatus.AdminStats.IncRequests()
env := envelope.NewEnvelope("domain/GET")
params := mux.Vars(r)
if id, ok := params["domain-name"]; !ok {
env.Error = "domain-name is missing"
env.ErrorURI = r.RequestURI
env.ErrorDescription = "domain API requires a domain-name"
} else {
domainName := id
if domainLB, ok := connectionTable.domains[domainName]; !ok {
env.Error = "domain-name was not found"
env.ErrorURI = r.RequestURI
env.ErrorDescription = "domain-name not found"
} else {
var domainAPIContainer []*ServerDomainAPI
conns := domainLB.Connections()
for pos := range conns {
conn := conns[pos]
domainAPI := NewServerDomainAPI(conn, conn.DomainTrack[domainName])
domainAPIContainer = append(domainAPIContainer, domainAPI)
}
env.Result = domainAPIContainer
}
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env.GenerateWriter(w)
serverStatus.AdminStats.IncResponses()
}
func getServersEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
serverStatus.AdminStats.IncRequests()
serverContainer := NewServerAPIContainer()
for c := range connectionTable.Connections() {
serverAPI := NewServersAPI(c)
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env := envelope.NewEnvelope("servers/GET")
env.Result = serverContainer
env.GenerateWriter(w)
serverStatus.AdminStats.IncResponses()
}
func getServerEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
serverStatus.AdminStats.IncRequests()
env := envelope.NewEnvelope("server/GET")
params := mux.Vars(r)
if id, ok := params["server-id"]; !ok {
env.Error = "server-id is missing"
env.ErrorURI = r.RequestURI
env.ErrorDescription = "server API requires a server-id"
} else {
serverID, err := strconv.Atoi(id)
if err != nil {
env.Error = "server-id is not an integer"
env.ErrorURI = r.RequestURI
env.ErrorDescription = "server API requires a server-id"
} else {
conn, err := connectionTable.GetConnection(int64(serverID))
if err != nil {
env.Error = "server-id was not found"
env.ErrorURI = r.RequestURI
env.ErrorDescription = "missing server-id, make sure desired service-id is in servers"
} else {
loginfo.Println("test")
serverAPI := NewServerAPI(conn)
env.Result = serverAPI
}
}
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env.GenerateWriter(w)
serverStatus.AdminStats.IncResponses()
}