Add webapi. Provides an HTTP API for clients to use Peernet.

This commit is contained in:
Kleissner
2021-09-10 13:40:07 +02:00
parent 928c16c492
commit 19e29b3a91
8 changed files with 1041 additions and 17 deletions

113
webapi/API.go Normal file
View File

@@ -0,0 +1,113 @@
/*
File Name: API.go
Copyright: 2021 Peernet Foundation s.r.o.
Author: Peter Kleissner
*/
package webapi
import (
"crypto/tls"
"encoding/json"
"errors"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
// Router can be used to register additional API functions
var Router *mux.Router
// WSUpgrader can be used to provide web sockets. It uses all default options and allows all requests.
var WSUpgrader = websocket.Upgrader{}
// Start starts the API. ListenAddresses is a list of IP:Ports
func Start(ListenAddresses []string, UseSSL bool, CertificateFile, CertificateKey string, TimeoutRead, TimeoutWrite time.Duration) {
if len(ListenAddresses) == 0 {
return
}
WSUpgrader.CheckOrigin = func(r *http.Request) bool {
return true
}
Router = mux.NewRouter()
Router.HandleFunc("/test", apiTest).Methods("GET")
Router.HandleFunc("/status", apiStatus).Methods("GET")
Router.HandleFunc("/peer/self", apiPeerSelf).Methods("GET")
Router.HandleFunc("/blockchain/self/header", apiBlockchainSelfHeader).Methods("GET")
Router.HandleFunc("/blockchain/self/append", apiBlockchainSelfAppend).Methods("POST")
Router.HandleFunc("/blockchain/self/read", apiBlockchainSelfRead).Methods("GET")
Router.HandleFunc("/blockchain/self/add/file", apiBlockchainSelfAddFile).Methods("POST")
Router.HandleFunc("/blockchain/self/list/file", apiBlockchainSelfListFile).Methods("GET")
Router.HandleFunc("/profile/list", apiProfileList).Methods("GET")
Router.HandleFunc("/profile/read", apiProfileRead).Methods("GET")
Router.HandleFunc("/profile/write", apiProfileWrite).Methods("POST")
for _, listen := range ListenAddresses {
go startWebServer(listen, UseSSL, CertificateFile, CertificateKey, Router, "API", TimeoutRead, TimeoutWrite)
}
}
// startWebServer starts a web-server with given parameters and logs the status. If may block forever and only returns if there is an error.
func startWebServer(WebListen string, UseSSL bool, CertificateFile, CertificateKey string, Handler http.Handler, Info string, ReadTimeout, WriteTimeout time.Duration) {
tlsConfig := &tls.Config{MinVersion: tls.VersionTLS12} // for security reasons disable TLS 1.0/1.1
server := &http.Server{
Addr: WebListen,
Handler: Handler,
ReadTimeout: ReadTimeout, // ReadTimeout is the maximum duration for reading the entire request, including the body.
WriteTimeout: WriteTimeout, // WriteTimeout is the maximum duration before timing out writes of the response. This includes processing time and is therefore the max time any HTTP function may take.
//IdleTimeout: IdleTimeout, // IdleTimeout is the maximum amount of time to wait for the next request when keep-alives are enabled.
TLSConfig: tlsConfig,
}
if UseSSL {
// HTTPS
if err := server.ListenAndServeTLS(CertificateFile, CertificateKey); err != nil {
log.Printf("Error listening on '%s': %v\n", WebListen, err)
}
} else {
// HTTP
if err := server.ListenAndServe(); err != nil {
log.Printf("Error listening on '%s': %v\n", WebListen, err)
}
}
}
func apiEncodeJSON(w http.ResponseWriter, r *http.Request, data interface{}) (err error) {
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(data)
if err != nil {
log.Printf("Error writing data for route '%s': %v\n", r.URL.Path, err)
}
return err
}
// apiDecodeJSON decodes input JSON data server side sent either via GET or POST. It does not limit the maximum amount to read.
// In case of error it will automatically send an error to the client.
func apiDecodeJSON(w http.ResponseWriter, r *http.Request, data interface{}) (err error) {
if r.Body == nil {
http.Error(w, "", http.StatusBadRequest)
return errors.New("no data")
}
err = json.NewDecoder(r.Body).Decode(data)
if err != nil {
http.Error(w, "", http.StatusBadRequest)
return err
}
return nil
}
func apiTest(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}