Skip to content

Commit

Permalink
dvovk/api fe serve (#26)
Browse files Browse the repository at this point in the history
* React UI test implementation

* added http as rest.port

* added rest.port (http)

* add _bin to gitignore

* _bin as dir

* mrg

* added browser open on start

* fixed build issue

* updated routing to be node and rest based

* merging

* merging

* updated FE build

* removed log file

* added cmdline and flags supports

* fix merge type changes

* added log processing updates

* Added lock to request inc

* updated FE

* added logs displaying

* add lock

* fixed json unmarshal breaks

* updated FE

* added db and sync stages support

* move base64 decode to unmarshal

* updated UI

* updated FE

* updated endpoints

* fixed query sync stages param to be base64url encoded

* updated build and documentation

* added find reorgs to REST API

* added fetching active peers

* added bootnodes query

* added diagnostics connection diagram

* updated documentation: updated, images, added network tab descrription

* changed peer data structure

* updated UI, updated peer diagnostics data structure

* updated UII

* updated UI

* updated UI

* updated readme

* updated UI

* added handling subpaths for FE

* fix tests

* fixed lint errors

* commented unused funcs

* fixed lint errors

* commented tests

* removed routerPort cfg var as it's never used

* WP serving API and FE from one port

* change serving ui to be on the same endpoint as API, changed serving API to have /api prefix in path

* added clear all data button on admin page

* added confirm popup for clear all data, updated readme

* removed tests

---------

Co-authored-by: Mark Holt <mark@distributed.vision>
  • Loading branch information
dvovk and mh0lt authored Nov 3, 2023
1 parent ce9fbf1 commit 281a922
Show file tree
Hide file tree
Showing 9 changed files with 748 additions and 89 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ If metrics are exposed, textual representation of metrics will be displayed in t
# How to connect Erigon node to the diagnostics system
![diagnostics system connection](/_images/diagnostics-connection-anim.gif)
#### Step 1:
The app's diagnostic user interface (UI) will automatically open at https://localhost:8000 after you run one of the following commands:
The app's diagnostic user interface (UI) will automatically open at https://localhost:8080 after you run one of the following commands:
```
./diagnostics --tls.cert demo-tls/diagnostics.crt --tls.key demo-tls/diagnostics-key.pem --tls.cacerts demo-tls/CA-cert.pem
```
Expand All @@ -209,10 +209,10 @@ or


#### Step 2:
In the same web browser, open a new tab and navigate to `https://localhost`. Please note that you may need to accept the security risks associated with the self-signed certificate. This action is required only the first time you access this URL, as your browser will remember your choice for subsequent visits.
Please note that you may need to accept the security risks associated with the self-signed certificate. This action is required only the first time you access this URL, as your browser will remember your choice for subsequent visits.

#### Step 3:
Return to the app's UI at https://localhost:8000. Follow these steps to create a session:
Follow these steps to create a session:

![create new operation session 1](/_images/create_session_1.png)

Expand Down Expand Up @@ -255,7 +255,7 @@ diagnostics system, start with `/support/` prefix, followed by the PIN of the se
`BridgeHandler` type.

Operators (those who are trying to assist the Erigon node users) also access Diagnostics system, but in the form of User Interface, built using HTML
and Javascript. The URLs used for such access, start with `ui/` prefix. In the code inside `cmd/root.go`, this corresponds to the `UiHandler` type.
and Javascript. The URLs used for such access, start with `ui/` prefix. In the code inside `cmd/root.go`, this corresponds to the `APIHandler` type.

![diagnostics system architecture](/_images/diagnostics.drawio.png)

Expand Down
40 changes: 20 additions & 20 deletions api/ui_handler.go → api/api_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/ledgerwatch/diagnostics/internal/sessions"
)

var _ http.Handler = &UIHandler{}
var _ http.Handler = &APIHandler{}

type GetVersionResponse struct {
NodeVersion uint64 `json:"node_version"`
Expand All @@ -27,13 +27,13 @@ type SessionResponse struct {
Nodes []*sessions.NodeInfo `json:"nodes"`
}

type UIHandler struct {
type APIHandler struct {
chi.Router
sessions sessions.CacheService
erigonNode erigon_node.Client
}

func (h *UIHandler) GetSession(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) GetSession(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, SessionId)

uiSession, ok := h.sessions.FindUISession(id)
Expand Down Expand Up @@ -66,7 +66,7 @@ func (h *UIHandler) GetSession(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Versions(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Versions(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -91,7 +91,7 @@ func (h *UIHandler) Versions(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) CMDLine(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) CMDLine(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -115,7 +115,7 @@ func (h *UIHandler) CMDLine(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Flags(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Flags(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -139,7 +139,7 @@ func (h *UIHandler) Flags(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Logs(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Logs(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -164,7 +164,7 @@ func (h *UIHandler) Logs(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Log(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Log(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand Down Expand Up @@ -220,7 +220,7 @@ func (h *UIHandler) Log(w http.ResponseWriter, r *http.Request) {
client.Log(r.Context(), w, file, offset, limit, len(download) > 0)
}

func (h *UIHandler) DBs(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) DBs(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -245,7 +245,7 @@ func (h *UIHandler) DBs(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Tables(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Tables(w http.ResponseWriter, r *http.Request) {
db, tables := path.Split(chi.URLParam(r, "*"))

if tables != "tables" {
Expand Down Expand Up @@ -277,7 +277,7 @@ func (h *UIHandler) Tables(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) ReOrg(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) ReOrg(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -300,7 +300,7 @@ func (h *UIHandler) ReOrg(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) BodiesDownload(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) BodiesDownload(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -311,7 +311,7 @@ func (h *UIHandler) BodiesDownload(w http.ResponseWriter, r *http.Request) {
client.BodiesDownload(r.Context(), w)
}

func (h *UIHandler) HeadersDownload(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) HeadersDownload(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -322,7 +322,7 @@ func (h *UIHandler) HeadersDownload(w http.ResponseWriter, r *http.Request) {
client.HeadersDownload(r.Context(), w)
}

func (h *UIHandler) SyncStages(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) SyncStages(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -347,7 +347,7 @@ func (h *UIHandler) SyncStages(w http.ResponseWriter, r *http.Request) {
w.Write(jsonData)
}

func (h *UIHandler) Peers(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Peers(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -373,7 +373,7 @@ func (h *UIHandler) Peers(w http.ResponseWriter, r *http.Request) {

}

func (h *UIHandler) Bootnodes(w http.ResponseWriter, r *http.Request) {
func (h *APIHandler) Bootnodes(w http.ResponseWriter, r *http.Request) {
client, err := h.findNodeClient(w, r)

if err != nil {
Expand All @@ -399,7 +399,7 @@ func (h *UIHandler) Bootnodes(w http.ResponseWriter, r *http.Request) {

}

func (h *UIHandler) findNodeClient(w http.ResponseWriter, r *http.Request) (erigon_node.Client, error) {
func (h *APIHandler) findNodeClient(w http.ResponseWriter, r *http.Request) (erigon_node.Client, error) {
sessionId := chi.URLParam(r, SessionId)
nodeId := chi.URLParam(r, NodeId)

Expand All @@ -418,11 +418,11 @@ func (h *UIHandler) findNodeClient(w http.ResponseWriter, r *http.Request) (erig
return nil, fmt.Errorf("unknown sessionId: %s", sessionId)
}

func NewUIHandler(
func NewAPIHandler(
sessions sessions.CacheService,
erigonNode erigon_node.Client,
) *UIHandler {
r := &UIHandler{
) *APIHandler {
r := &APIHandler{
Router: chi.NewRouter(),
sessions: sessions,
erigonNode: erigonNode,
Expand Down
2 changes: 1 addition & 1 deletion api/bridge_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/pkg/errors"
)

var _ http.Handler = &UIHandler{}
var _ http.Handler = &APIHandler{}

type BridgeHandler struct {
chi.Router
Expand Down
18 changes: 17 additions & 1 deletion api/main_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ledgerwatch/diagnostics/api/internal"
"github.com/ledgerwatch/diagnostics/internal/erigon_node"
"github.com/ledgerwatch/diagnostics/internal/sessions"
"github.com/ledgerwatch/diagnostics/web"
)

type APIServices struct {
Expand All @@ -33,11 +34,26 @@ func NewHandler(services APIServices) http.Handler {
r.Mount(internal.HealthCheckEndPoint, HealthCheckHandler())
r.Mount(internal.BridgeEndPoint, NewBridgeHandler(services.StoreSession))

r.Mount("/", web.UI)
r.HandleFunc("/network", index)
r.HandleFunc("/logs", index)
r.HandleFunc("/chain", index)
r.HandleFunc("/data", index)
r.HandleFunc("/debug", index)
r.HandleFunc("/testing", index)
r.HandleFunc("/performance", index)
r.HandleFunc("/documentation", index)
r.HandleFunc("/admin", index)

r.Group(func(r chi.Router) {
session := sessions.Middleware{CacheService: services.StoreSession}
r.Use(session.Middleware)
r.Mount("/", NewUIHandler(services.StoreSession, services.ErigonNode))
r.Mount("/api", NewAPIHandler(services.StoreSession, services.ErigonNode))
})

return r
}

func index(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./../../web/dist/index.html")
}
Binary file added build/bin/golangci-lint
Binary file not shown.
62 changes: 1 addition & 61 deletions cmd/diagnostics/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,63 +75,7 @@ func main() {
}
}()

if routerPort > 0 {
srv := &http.Server{
Addr: fmt.Sprintf("%s:%d", listenAddr, routerPort),
Handler: handlers,
MaxHeaderBytes: 1 << 20,
ReadHeaderTimeout: 1 * time.Minute,
}

go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}
}()

}

r := http.NewServeMux()

r.HandleFunc("/network", index)
r.HandleFunc("/logs", index)
r.HandleFunc("/chain", index)
r.HandleFunc("/data", index)
r.HandleFunc("/debug", index)
r.HandleFunc("/testing", index)
r.HandleFunc("/performance", index)
r.HandleFunc("/documentation", index)
r.HandleFunc("/admin", index)
buildHandler := http.FileServer(http.Dir("./../../web/dist"))
r.Handle("/", buildHandler)

server := &http.Server{
Handler: r,
Addr: "127.0.0.1:8000",
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}

go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}
}()

/*http.Handle("/", web.UI)
server := &http.Server{
Addr: ":8000",
ReadHeaderTimeout: 3 * time.Second,
}
go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}
}()*/

open("http://localhost:8000")
open("https://localhost:8080")

// Graceful and eager terminations
switch s := <-signalCh; s {
Expand All @@ -146,10 +90,6 @@ func main() {
}
}

func index(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./../../web/dist/index.html")
}

// open opens the specified URL in the default browser of the user.
func open(url string) error {
var cmd string
Expand Down
Loading

0 comments on commit 281a922

Please sign in to comment.