mirror of
https://github.com/filebrowser/filebrowser.git
synced 2026-01-22 18:27:42 +00:00
82 lines
1.6 KiB
Go
82 lines
1.6 KiB
Go
package fbhttp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/filebrowser/filebrowser/v2/search"
|
|
)
|
|
|
|
const searchPingInterval = 5
|
|
|
|
var searchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
response := make(chan map[string]interface{})
|
|
ctx, cancel := context.WithCancelCause(r.Context())
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
// Avoid connection timeout
|
|
timeout := time.NewTimer(searchPingInterval * time.Second)
|
|
defer timeout.Stop()
|
|
for {
|
|
var err error
|
|
var infoBytes []byte
|
|
select {
|
|
case info := <-response:
|
|
if info == nil {
|
|
return
|
|
}
|
|
infoBytes, err = json.Marshal(info)
|
|
case <-timeout.C:
|
|
// Send a heartbeat packet
|
|
infoBytes = nil
|
|
case <-ctx.Done():
|
|
return
|
|
}
|
|
if err != nil {
|
|
cancel(err)
|
|
return
|
|
}
|
|
_, err = w.Write(infoBytes)
|
|
if err == nil {
|
|
_, err = w.Write([]byte("\n"))
|
|
}
|
|
if err != nil {
|
|
cancel(err)
|
|
return
|
|
}
|
|
if flusher, ok := w.(http.Flusher); ok {
|
|
flusher.Flush()
|
|
}
|
|
}
|
|
}()
|
|
query := r.URL.Query().Get("query")
|
|
|
|
err := search.Search(ctx, d.user.Fs, r.URL.Path, query, d, func(path string, f os.FileInfo) error {
|
|
select {
|
|
case <-ctx.Done():
|
|
case response <- map[string]interface{}{
|
|
"dir": f.IsDir(),
|
|
"path": path,
|
|
}:
|
|
}
|
|
return context.Cause(ctx)
|
|
})
|
|
close(response)
|
|
wg.Wait()
|
|
if err == nil {
|
|
err = context.Cause(ctx)
|
|
}
|
|
// ignore cancellation errors from user aborts
|
|
if err != nil && !errors.Is(err, context.Canceled) {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
return 0, nil
|
|
})
|