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"
|
||||
)
|
||||
|
||||
//ServerAPI -- Structure to support the server API
|
||||
type ServerAPI struct {
|
||||
//ServersAPI -- Structure to support the server API
|
||||
type ServersAPI 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)
|
||||
//NewServersAPI - Constructor
|
||||
func NewServersAPI(c *Connection) (s *ServersAPI) {
|
||||
s = new(ServersAPI)
|
||||
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()
|
||||
|
||||
for d := range c.DomainTrack {
|
||||
dt := c.DomainTrack[d]
|
||||
|
@ -33,12 +37,12 @@ func NewServerAPI(c *Connection) (s *ServerAPI) {
|
|||
|
||||
//ServerAPIContainer -- Holder for all the Servers
|
||||
type ServerAPIContainer struct {
|
||||
Servers []*ServerAPI `json:"servers"`
|
||||
Servers []*ServersAPI `json:"servers"`
|
||||
}
|
||||
|
||||
//NewServerAPIContainer -- Constructor
|
||||
func NewServerAPIContainer() (p *ServerAPIContainer) {
|
||||
p = new(ServerAPIContainer)
|
||||
p.Servers = make([]*ServerAPI, 0)
|
||||
p.Servers = make([]*ServersAPI, 0)
|
||||
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 (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.daplie.com/Daplie/go-rvpn-server/rvpn/envelope"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const (
|
||||
rDNSPackageName = "com.daplie.rvpn"
|
||||
endPointPrefix = "/api/com.daplie.rvpn/"
|
||||
)
|
||||
|
||||
var connectionTable *Table
|
||||
|
@ -23,8 +25,6 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
|||
connectionTable = ctx.Value(ctxConnectionTable).(*Table)
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
|
||||
endpoints := make(map[string]string)
|
||||
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
loginfo.Println("HandleFunc /")
|
||||
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) {
|
||||
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{
|
||||
Addr: ":80",
|
||||
|
@ -63,17 +65,60 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
|||
}
|
||||
}
|
||||
|
||||
func apiServers(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("here")
|
||||
func getServersEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
pc, _, _, _ := runtime.Caller(0)
|
||||
loginfo.Println(runtime.FuncForPC(pc).Name())
|
||||
|
||||
serverContainer := NewServerAPIContainer()
|
||||
|
||||
for c := range connectionTable.Connections() {
|
||||
serverAPI := NewServerAPI(c)
|
||||
serverAPI := NewServersAPI(c)
|
||||
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
|
||||
|
||||
}
|
||||
|
||||
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 bool
|
||||
|
||||
//connectionID
|
||||
connectionID int64
|
||||
}
|
||||
|
||||
//NewConnection -- Constructor
|
||||
func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress string, initialDomains []interface{}, connectionTrack *Tracking) (p *Connection) {
|
||||
connectionID = connectionID + 1
|
||||
|
||||
p = new(Connection)
|
||||
p.mutex = &sync.Mutex{}
|
||||
p.connectionTable = connectionTable
|
||||
|
@ -85,6 +90,7 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s
|
|||
}
|
||||
|
||||
p.State(true)
|
||||
p.connectionID = connectionID
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -124,6 +130,11 @@ func (c *Connection) SendCh() chan *SendTrack {
|
|||
return c.send
|
||||
}
|
||||
|
||||
//Source --
|
||||
func (c *Connection) Source() string {
|
||||
return c.source
|
||||
}
|
||||
|
||||
func (c *Connection) addIn(num int64) {
|
||||
c.bytesIn = c.bytesIn + num
|
||||
}
|
||||
|
@ -167,6 +178,11 @@ func (c *Connection) Update() {
|
|||
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
|
||||
//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
|
||||
|
|
|
@ -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
|
||||
func (c *Table) Run(ctx context.Context) {
|
||||
loginfo.Println("ConnectionTable starting")
|
||||
|
|
|
@ -3,15 +3,21 @@ package genericlistener
|
|||
import (
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
loginfo *log.Logger
|
||||
logdebug *log.Logger
|
||||
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
|
||||
connectionID int64
|
||||
)
|
||||
|
||||
func init() {
|
||||
loginfo = log.New(os.Stdout, "INFO: 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