Skip to content

Commit

Permalink
Merge pull request #210 from cmsax/main
Browse files Browse the repository at this point in the history
feat: add an HTTP server to enable users to monitor status updates via status bars or other UI components.
  • Loading branch information
schollz authored Dec 9, 2024
2 parents 77ce0b9 + d4ec079 commit d88592d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
28 changes: 28 additions & 0 deletions progressbar.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package progressbar

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"math"
"net/http"
"os"
"regexp"
"strings"
Expand Down Expand Up @@ -1009,6 +1012,31 @@ func (p *ProgressBar) State() State {
return s
}

// StartHTTPServer starts an HTTP server dedicated to serving progress bar updates. This allows you to
// display the status in various UI elements, such as an OS status bar with an `xbar` extension.
// It is recommended to run this function in a separate goroutine to avoid blocking the main thread.
//
// hostPort specifies the address and port to bind the server to, for example, "0.0.0.0:19999".
func (p *ProgressBar) StartHTTPServer(hostPort string) {
// for advanced users, we can return the data as json
http.HandleFunc("/state", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/json")
// since the state is a simple struct, we can just ignore the error
bs, _ := json.Marshal(p.State())
w.Write(bs)
})
// for others, we just return the description in a plain text format
http.HandleFunc("/desc", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w,
"%d/%d, %.2f%%, %s left",
p.State().CurrentNum, p.State().Max, p.State().CurrentPercent*100,
(time.Second * time.Duration(p.State().SecondsLeft)).String(),
)
})
log.Fatal(http.ListenAndServe(hostPort, nil))
}

// regex matching ansi escape codes
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)

Expand Down
40 changes: 40 additions & 0 deletions progressbar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -1123,3 +1124,42 @@ func TestOptionShowTotalTrueIndeterminate(t *testing.T) {
t.Errorf("wrong string: %s", buf.String())
}
}

func TestStartHTTPServer(t *testing.T) {
bar := Default(10, "test")
bar.Add(1)

hostPort := "localhost:9696"
go bar.StartHTTPServer(hostPort)

// check plain text
resp, err := http.Get(fmt.Sprintf("http://%s/desc", hostPort))
if err != nil {
t.Error(err)
}
got, err := io.ReadAll(resp.Body)
if err != nil {
t.Error(err)
}
if string(got) != "1/10, 10.00%, 0s left" {
t.Errorf("wrong string: %s", string(got))
}

// check json
resp, err = http.Get(fmt.Sprintf("http://%s/state", hostPort))
if err != nil {
t.Error(err)
}
got, err = io.ReadAll(resp.Body)
if err != nil {
t.Error(err)
}
var result State
err = json.Unmarshal(got, &result)
if err != nil {
t.Error(err)
}
if result.Max != bar.State().Max || result.CurrentNum != bar.State().CurrentNum {
t.Errorf("wrong state: %v", result)
}
}

0 comments on commit d88592d

Please sign in to comment.