frontend: add API

This commit is contained in:
Lan Tian
2021-01-17 12:35:29 +08:00
parent aa76bc3de7
commit da2c3d9aed
5 changed files with 347 additions and 28 deletions

116
frontend/api.go Normal file
View File

@@ -0,0 +1,116 @@
package main
import (
"encoding/json"
"errors"
"net/http"
)
type apiRequest struct {
Servers []string `json:"servers"`
Type string `json:"type"`
Args string `json:"args"`
}
type apiGenericResultPair struct {
Server string `json:"server"`
Data string `json:"data"`
}
type apiSummaryResultPair struct {
Server string `json:"server"`
Data []SummaryRowData `json:"data"`
}
type apiResponse struct {
Error string `json:"error"`
Result []interface{} `json:"result"`
}
var apiHandlerMap = map[string](func(request apiRequest) apiResponse){
"summary": apiSummaryHandler,
"bird": apiGenericHandlerFactory("bird"),
"traceroute": apiGenericHandlerFactory("traceroute"),
"whois": apiWhoisHandler,
}
func apiGenericHandlerFactory(endpoint string) func(request apiRequest) apiResponse {
return func(request apiRequest) apiResponse {
results := batchRequest(request.Servers, endpoint, request.Args)
var response apiResponse
for i, result := range results {
response.Result = append(response.Result, &apiGenericResultPair{
Server: request.Servers[i],
Data: result,
})
}
return response
}
}
func apiSummaryHandler(request apiRequest) apiResponse {
results := batchRequest(request.Servers, "bird", "show protocols")
var response apiResponse
for i, result := range results {
parsedSummary, err := summaryParse(result, request.Servers[i])
if err != nil {
return apiResponse{
Error: err.Error(),
}
}
response.Result = append(response.Result, &apiSummaryResultPair{
Server: request.Servers[i],
Data: parsedSummary.Rows,
})
}
return response
}
func apiWhoisHandler(request apiRequest) apiResponse {
return apiResponse{
Error: "",
Result: []interface{}{
apiGenericResultPair{
Server: "",
Data: whois(request.Args),
},
},
}
}
func apiErrorHandler(err error) apiResponse {
return apiResponse{
Error: err.Error(),
}
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
var request apiRequest
var response apiResponse
err := json.NewDecoder(r.Body).Decode(&request)
if err != nil {
response = apiResponse{
Error: err.Error(),
}
} else {
handler := apiHandlerMap[request.Type]
if handler == nil {
response = apiErrorHandler(errors.New("Invalid request type"))
} else {
response = handler(request)
}
}
w.Header().Add("Content-Type", "application/json")
bytes, err := json.Marshal(response)
if err != nil {
println(err.Error())
return
}
w.Write(bytes)
}

View File

@@ -2,6 +2,7 @@ package main
import (
"bytes"
"errors"
"fmt"
"net/http"
"regexp"
@@ -99,18 +100,17 @@ func smartFormatter(s string) string {
return result
}
// Output a table for the summary page
func summaryTable(data string, serverName string) string {
// Parse bird show protocols result
func summaryParse(data string, serverName string) (TemplateSummary, error) {
args := TemplateSummary{
ServerName: serverName,
Raw: data,
}
lines := strings.Split(strings.TrimSpace(data), "\n")
if len(lines) <= 1 {
// Likely backend returned an error message
return "<pre>" + template.HTMLEscapeString(strings.TrimSpace(data)) + "</pre>"
}
args := TemplateSummary{
ServerName: serverName,
Raw: data,
return args, errors.New(strings.TrimSpace(data))
}
// extract the table header
@@ -167,10 +167,21 @@ func summaryTable(data string, serverName string) string {
args.Rows = append(args.Rows, row)
}
// finally, render the summary template
return args, nil
}
// Output a table for the summary page
func summaryTable(data string, serverName string) string {
result, err := summaryParse(data, serverName)
if err != nil {
return "<pre>" + template.HTMLEscapeString(err.Error()) + "</pre>"
}
// render the summary template
tmpl := TemplateLibrary["summary"]
var buffer bytes.Buffer
err := tmpl.Execute(&buffer, args)
err = tmpl.Execute(&buffer, result)
if err != nil {
fmt.Println("Error rendering summary:", err.Error())
}

View File

@@ -32,15 +32,14 @@ type TemplatePage struct {
}
// summary
type SummaryRowData struct {
Name string
Proto string
Table string
State string
MappedState string
Since string
Info string
Name string `json:"name"`
Proto string `json:"proto"`
Table string `json:"table"`
State string `json:"state"`
MappedState string `json:"-"`
Since string `json:"since"`
Info string `json:"info"`
}
// utility functions to allow filtering of results in the template

View File

@@ -210,6 +210,7 @@ func webServerStart() {
http.HandleFunc("/generic/", webBackendCommunicator("bird", "generic"))
http.HandleFunc("/traceroute/", webBackendCommunicator("traceroute", "traceroute"))
http.HandleFunc("/whois/", webHandlerWhois)
http.HandleFunc("/api/", apiHandler)
http.HandleFunc("/telegram/", webHandlerTelegramBot)
// Start HTTP server