func HtdigestFileProvider(filename string) SecretProvider {
	hf := &HtdigestFile{File: File{Path: filename}}
	hf.Reload = func() { reloadHTDigest(hf) }
	return func(user, realm string) string {
		hf.ReloadIfNeeded()
		hf.mu.RLock()
		defer hf.mu.RUnlock()
		_, exists := hf.Users[realm]
		if !exists {
			return ""
		}
		digest, exists := hf.Users[realm][user]
		if !exists {
			return ""
		}
		return digest
	}
}
HtdigestFileProvider is a SecretProvider implementation based on
htdigest-formated files. It will automatically reload htdigest file
on changes. It panics on syntax errors in htdigest files.
package auth
import (
	"encoding/csv"
	"os"
	"sync"
)
type SecretProvider func(user, realm string) string
type File struct {
	Path string
	Info os.FileInfo
	Reload func()
	mu     sync.Mutex
}
func (f *File) ReloadIfNeeded() {
	info, err := os.Stat(f.Path)
	if err != nil {
		panic(err)
	}
	f.mu.Lock()
	defer f.mu.Unlock()
	if f.Info == nil || f.Info.ModTime() != info.ModTime() {
		f.Info = info
		f.Reload()
	}
}
type HtdigestFile struct {
	File
	Users map[string]map[string]string
	mu    sync.RWMutex
}
func reloadHTDigest(hf *HtdigestFile) {
	r, err := os.Open(hf.Path)
	if err != nil {
		panic(err)
	}
	reader := csv.NewReader(r)
	reader.Comma = ':'
	reader.Comment = '#'
	reader.TrimLeadingSpace = true
	records, err := reader.ReadAll()
	if err != nil {
		panic(err)
	}
	hf.mu.Lock()
	defer hf.mu.Unlock()
	hf.Users = make(map[string]map[string]string)
	for _, record := range records {
		_, exists := hf.Users[record[1]]
		if !exists {
			hf.Users[record[1]] = make(map[string]string)
		}
		hf.Users[record[1]][record[0]] = record[2]
	}
}