goveal/internal/app/server/hash_handler.go
Peter Kurfer b953310df8
Do not cache files that are monitored
- rename repo to goveal
- add working directory option
- remove most CLI switches in favor of config file
2020-12-06 12:18:42 +01:00

103 lines
2.1 KiB
Go

package server
import (
"crypto"
"encoding/hex"
"encoding/json"
"hash"
"io"
"net/http"
"regexp"
"strings"
"sync"
log "github.com/sirupsen/logrus"
"go.uber.org/multierr"
)
var (
pathMatcherRegexp = regexp.MustCompile(`(?i)^/hash/(md5|sha1|sha2)(/.*)`)
hashes = map[string]crypto.Hash{
"md5": crypto.MD5,
"sha1": crypto.SHA1,
"sha256": crypto.SHA256,
}
)
type hashResponse struct {
FilePath string
Hash string
}
func NewHashHandler(fs http.FileSystem) http.Handler {
return &hashHandler{
fs: fs,
bufferPool: &sync.Pool{
New: func() interface{} {
return make([]byte, 4096)
},
},
}
}
type hashHandler struct {
bufferPool *sync.Pool
fs http.FileSystem
}
func (h hashHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
components := pathMatcherRegexp.FindStringSubmatch(request.URL.Path)
if len(components) != 3 {
writer.WriteHeader(400)
return
}
filePath := components[2]
var hashFound bool
var hashInstance crypto.Hash
if hashInstance, hashFound = hashes[strings.ToLower(components[1])]; !hashFound {
writer.WriteHeader(404)
return
}
var f http.File
var err error
if f, err = h.fs.Open(filePath); err != nil {
writer.WriteHeader(404)
return
}
var encodedHash string
if encodedHash, err = h.buildHash(hashInstance.New(), f); err != nil {
log.Errorf("Failed to calculate hash %v", err)
writer.WriteHeader(500)
return
}
resp := hashResponse{
FilePath: filePath,
Hash: encodedHash,
}
writer.Header().Set("Content-Type", "application/json")
encoder := json.NewEncoder(writer)
if err = encoder.Encode(resp); err != nil {
writer.WriteHeader(500)
return
}
}
func (h *hashHandler) buildHash(hasher hash.Hash, src io.ReadCloser) (encodedHash string, err error) {
defer func() {
err = multierr.Append(err, src.Close())
}()
buffer := h.bufferPool.Get().([]byte)
for n, err := src.Read(buffer); n > 0 && err == nil; n, err = src.Read(buffer) {
if _, err := hasher.Write(buffer[:n]); err != nil {
return "", err
}
}
encodedHash = hex.EncodeToString(hasher.Sum(nil))
return
}