API Rest Interface answers to servers and server/{id}
- built envelope based on AJ spec, self standing package with transaction ID increment and unix time stamps - fixed servers end point - created server/{id} end point - created rest mappings for GET
This commit is contained in:
parent
b88817e4d1
commit
dd7d63baf6
|
@ -0,0 +1,43 @@
|
||||||
|
package envelope
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
import "encoding/json"
|
||||||
|
import "bytes"
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
//Envelope -- Standard daplie response structure
|
||||||
|
type Envelope struct {
|
||||||
|
TransactionType string `json:"type"`
|
||||||
|
Schema string `json:"schema"`
|
||||||
|
TransactionTimeStamp int64 `json:"txts"`
|
||||||
|
TransactionID int64 `json:"txid"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
ErrorDescription string `json:"error_description"`
|
||||||
|
ErrorURI string `json:"error_uri"`
|
||||||
|
Result interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewEnvelope -- Constructor
|
||||||
|
func NewEnvelope(transactionType string) (p *Envelope) {
|
||||||
|
transactionID++
|
||||||
|
|
||||||
|
p = new(Envelope)
|
||||||
|
p.TransactionType = transactionType
|
||||||
|
p.TransactionID = transactionID
|
||||||
|
p.TransactionTimeStamp = time.Now().Unix()
|
||||||
|
p.Error = "ok"
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate -- encode into JSON and return string
|
||||||
|
func (e *Envelope) Generate() string {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
json.NewEncoder(buf).Encode(e)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
//GenerateWriter --
|
||||||
|
func (e *Envelope) GenerateWriter(w io.Writer) {
|
||||||
|
json.NewEncoder(w).Encode(e)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package envelope
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
loginfo *log.Logger
|
||||||
|
logdebug *log.Logger
|
||||||
|
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
|
||||||
|
transactionID int64
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
loginfo = log.New(os.Stdout, "INFO: envelope: ", logFlags)
|
||||||
|
logdebug = log.New(os.Stdout, "DEBUG: envelope:", logFlags)
|
||||||
|
transactionID = 1
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package genericlistener
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//ServerAPI -- Structure to support the server API
|
||||||
|
type ServerAPI struct {
|
||||||
|
ServerName string `json:"server_name"`
|
||||||
|
ServerID int64 `json:"server_id"`
|
||||||
|
Domains []*DomainAPI `json:"domains"`
|
||||||
|
Duration float64 `json:"duration"`
|
||||||
|
BytesIn int64 `json:"bytes_in"`
|
||||||
|
BytesOut int64 `json:"bytes_out"`
|
||||||
|
Source string `json:"source_address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewServerAPI - Constructor
|
||||||
|
func NewServerAPI(c *Connection) (s *ServerAPI) {
|
||||||
|
s = new(ServerAPI)
|
||||||
|
s.ServerName = fmt.Sprintf("%p", c)
|
||||||
|
s.ServerID = c.ConnectionID()
|
||||||
|
s.Domains = make([]*DomainAPI, 0)
|
||||||
|
s.Duration = time.Since(c.ConnectTime()).Seconds()
|
||||||
|
s.BytesIn = c.BytesIn()
|
||||||
|
s.BytesOut = c.BytesOut()
|
||||||
|
s.Source = c.source
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -5,23 +5,27 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//ServerAPI -- Structure to support the server API
|
//ServersAPI -- Structure to support the server API
|
||||||
type ServerAPI struct {
|
type ServersAPI struct {
|
||||||
ServerName string `json:"server_name"`
|
ServerName string `json:"server_name"`
|
||||||
|
ServerID int64 `json:"server_id"`
|
||||||
Domains []*DomainAPI `json:"domains"`
|
Domains []*DomainAPI `json:"domains"`
|
||||||
Duration float64 `json:"duration"`
|
Duration float64 `json:"duration"`
|
||||||
BytesIn int64 `json:"bytes_in"`
|
BytesIn int64 `json:"bytes_in"`
|
||||||
BytesOut int64 `json:"bytes_out"`
|
BytesOut int64 `json:"bytes_out"`
|
||||||
|
Source string `json:"source_address"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewServerAPI - Constructor
|
//NewServersAPI - Constructor
|
||||||
func NewServerAPI(c *Connection) (s *ServerAPI) {
|
func NewServersAPI(c *Connection) (s *ServersAPI) {
|
||||||
s = new(ServerAPI)
|
s = new(ServersAPI)
|
||||||
s.ServerName = fmt.Sprintf("%p", c)
|
s.ServerName = fmt.Sprintf("%p", c)
|
||||||
|
s.ServerID = c.ConnectionID()
|
||||||
s.Domains = make([]*DomainAPI, 0)
|
s.Domains = make([]*DomainAPI, 0)
|
||||||
s.Duration = time.Since(c.ConnectTime()).Seconds()
|
s.Duration = time.Since(c.ConnectTime()).Seconds()
|
||||||
s.BytesIn = c.BytesIn()
|
s.BytesIn = c.BytesIn()
|
||||||
s.BytesOut = c.BytesOut()
|
s.BytesOut = c.BytesOut()
|
||||||
|
s.Source = c.Source()
|
||||||
|
|
||||||
for d := range c.DomainTrack {
|
for d := range c.DomainTrack {
|
||||||
dt := c.DomainTrack[d]
|
dt := c.DomainTrack[d]
|
||||||
|
@ -33,12 +37,12 @@ func NewServerAPI(c *Connection) (s *ServerAPI) {
|
||||||
|
|
||||||
//ServerAPIContainer -- Holder for all the Servers
|
//ServerAPIContainer -- Holder for all the Servers
|
||||||
type ServerAPIContainer struct {
|
type ServerAPIContainer struct {
|
||||||
Servers []*ServerAPI `json:"servers"`
|
Servers []*ServersAPI `json:"servers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewServerAPIContainer -- Constructor
|
//NewServerAPIContainer -- Constructor
|
||||||
func NewServerAPIContainer() (p *ServerAPIContainer) {
|
func NewServerAPIContainer() (p *ServerAPIContainer) {
|
||||||
p = new(ServerAPIContainer)
|
p = new(ServerAPIContainer)
|
||||||
p.Servers = make([]*ServerAPI, 0)
|
p.Servers = make([]*ServersAPI, 0)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
package genericlistener
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
type apiEndPoint struct {
|
|
||||||
pack string
|
|
||||||
endpoint string
|
|
||||||
method func(w http.ResponseWriter, r *http.Request)
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIEndPoints struct {
|
|
||||||
endPoint map[string]*apiEndPoint
|
|
||||||
}
|
|
||||||
|
|
||||||
//NewAPIEndPoints -- Constructor
|
|
||||||
func NewAPIEndPoints() (p *APIEndPoints) {
|
|
||||||
p = new(apiEndPoints)
|
|
||||||
p.endPoint = make(map[string]*apiEndPoint)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *apiEndPoints) add(pack string, endpoint string, method func(w http.ResponseWriter, r *http.Request)) {
|
|
||||||
|
|
||||||
router.HandleFunc("/api/"+rDNSPackageName+"servers", apiServers)
|
|
||||||
}
|
|
|
@ -2,16 +2,18 @@ package genericlistener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.daplie.com/Daplie/go-rvpn-server/rvpn/envelope"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rDNSPackageName = "com.daplie.rvpn"
|
endPointPrefix = "/api/com.daplie.rvpn/"
|
||||||
)
|
)
|
||||||
|
|
||||||
var connectionTable *Table
|
var connectionTable *Table
|
||||||
|
@ -23,8 +25,6 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
||||||
connectionTable = ctx.Value(ctxConnectionTable).(*Table)
|
connectionTable = ctx.Value(ctxConnectionTable).(*Table)
|
||||||
router := mux.NewRouter().StrictSlash(true)
|
router := mux.NewRouter().StrictSlash(true)
|
||||||
|
|
||||||
endpoints := make(map[string]string)
|
|
||||||
|
|
||||||
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
loginfo.Println("HandleFunc /")
|
loginfo.Println("HandleFunc /")
|
||||||
switch url := r.URL.Path; url {
|
switch url := r.URL.Path; url {
|
||||||
|
@ -41,10 +41,12 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
||||||
|
|
||||||
router.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) {
|
router.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
fmt.Fprintln(w, "<html>Welcome..press <a href=/api/servers>Servers</a> to access stats</html>")
|
fmt.Fprintln(w, "<html>Welcome..press <a href=/api/com.daplie.rvpn/servers>Servers</a> to access stats</html>")
|
||||||
})
|
})
|
||||||
|
|
||||||
router.HandleFunc("/api/"+rDNSPackageName+"servers", apiServers)
|
router.HandleFunc(endPointPrefix+"servers", getServersEndpoint).Methods("GET")
|
||||||
|
router.HandleFunc(endPointPrefix+"server/", getServerEndpoint).Methods("GET")
|
||||||
|
router.HandleFunc(endPointPrefix+"server/{server-id}", getServerEndpoint).Methods("GET")
|
||||||
|
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: ":80",
|
Addr: ":80",
|
||||||
|
@ -63,17 +65,60 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiServers(w http.ResponseWriter, r *http.Request) {
|
func getServersEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Println("here")
|
pc, _, _, _ := runtime.Caller(0)
|
||||||
|
loginfo.Println(runtime.FuncForPC(pc).Name())
|
||||||
|
|
||||||
serverContainer := NewServerAPIContainer()
|
serverContainer := NewServerAPIContainer()
|
||||||
|
|
||||||
for c := range connectionTable.Connections() {
|
for c := range connectionTable.Connections() {
|
||||||
serverAPI := NewServerAPI(c)
|
serverAPI := NewServersAPI(c)
|
||||||
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
|
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
json.NewEncoder(w).Encode(serverContainer)
|
|
||||||
|
env := envelope.NewEnvelope("servers/GET")
|
||||||
|
env.Result = serverContainer
|
||||||
|
env.GenerateWriter(w)
|
||||||
|
|
||||||
|
//json.NewEncoder(w).Encode(serverContainer)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getServerEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
|
pc, _, _, _ := runtime.Caller(0)
|
||||||
|
loginfo.Println(runtime.FuncForPC(pc).Name())
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -63,10 +63,15 @@ type Connection struct {
|
||||||
|
|
||||||
///wssState tracks a highlevel status of the connection, false means do nothing.
|
///wssState tracks a highlevel status of the connection, false means do nothing.
|
||||||
wssState bool
|
wssState bool
|
||||||
|
|
||||||
|
//connectionID
|
||||||
|
connectionID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewConnection -- Constructor
|
//NewConnection -- Constructor
|
||||||
func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress string, initialDomains []interface{}, connectionTrack *Tracking) (p *Connection) {
|
func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress string, initialDomains []interface{}, connectionTrack *Tracking) (p *Connection) {
|
||||||
|
connectionID = connectionID + 1
|
||||||
|
|
||||||
p = new(Connection)
|
p = new(Connection)
|
||||||
p.mutex = &sync.Mutex{}
|
p.mutex = &sync.Mutex{}
|
||||||
p.connectionTable = connectionTable
|
p.connectionTable = connectionTable
|
||||||
|
@ -85,6 +90,7 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s
|
||||||
}
|
}
|
||||||
|
|
||||||
p.State(true)
|
p.State(true)
|
||||||
|
p.connectionID = connectionID
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +130,11 @@ func (c *Connection) SendCh() chan *SendTrack {
|
||||||
return c.send
|
return c.send
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Source --
|
||||||
|
func (c *Connection) Source() string {
|
||||||
|
return c.source
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Connection) addIn(num int64) {
|
func (c *Connection) addIn(num int64) {
|
||||||
c.bytesIn = c.bytesIn + num
|
c.bytesIn = c.bytesIn + num
|
||||||
}
|
}
|
||||||
|
@ -167,6 +178,11 @@ func (c *Connection) Update() {
|
||||||
c.lastUpdate = time.Now()
|
c.lastUpdate = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ConnectionID - Get
|
||||||
|
func (c *Connection) ConnectionID() int64 {
|
||||||
|
return c.connectionID
|
||||||
|
}
|
||||||
|
|
||||||
//NextWriter -- Wrapper to allow a high level state check before offering NextWriter
|
//NextWriter -- Wrapper to allow a high level state check before offering NextWriter
|
||||||
//The libary failes if client abends during write-cycle. a fast moving write is not caught before socket state bubbles up
|
//The libary failes if client abends during write-cycle. a fast moving write is not caught before socket state bubbles up
|
||||||
//A synchronised state is maintained
|
//A synchronised state is maintained
|
||||||
|
|
|
@ -66,6 +66,19 @@ func (c *Table) reaper(delay int, idle int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//GetConnection -- find connection by server-id
|
||||||
|
func (c *Table) GetConnection(serverID int64) (conn *Connection, err error) {
|
||||||
|
for conn := range c.connections {
|
||||||
|
if conn.ConnectionID() == serverID {
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fmt.Errorf("Server-id %d not found", serverID)
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
//Run -- Execute
|
//Run -- Execute
|
||||||
func (c *Table) Run(ctx context.Context) {
|
func (c *Table) Run(ctx context.Context) {
|
||||||
loginfo.Println("ConnectionTable starting")
|
loginfo.Println("ConnectionTable starting")
|
||||||
|
|
|
@ -3,15 +3,21 @@ package genericlistener
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
loginfo *log.Logger
|
loginfo *log.Logger
|
||||||
logdebug *log.Logger
|
logdebug *log.Logger
|
||||||
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
|
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
|
||||||
|
connectionID int64
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
loginfo = log.New(os.Stdout, "INFO: genericlistener: ", logFlags)
|
loginfo = log.New(os.Stdout, "INFO: genericlistener: ", logFlags)
|
||||||
logdebug = log.New(os.Stdout, "DEBUG: genericlistener:", logFlags)
|
logdebug = log.New(os.Stdout, "DEBUG: genericlistener:", logFlags)
|
||||||
|
pc, _, _, _ := runtime.Caller(0)
|
||||||
|
loginfo.Println(runtime.FuncForPC(pc).Name())
|
||||||
|
|
||||||
|
connectionID = 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue