read configuration file

This commit is contained in:
Xavier Henner
2019-07-08 22:32:12 +02:00
parent 9dc7d19811
commit dd38706b0b
30 changed files with 3621 additions and 24 deletions

View File

View File

@@ -0,0 +1,38 @@
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"github.com/pyke369/golang-support/rpack"
)
func main() {
var (
options flag.FlagSet
usemain bool
)
options = flag.FlagSet{Usage: func() {
fmt.Fprintf(os.Stderr, "usage: %s [options] rootdir\n\noptions are:\n\n", filepath.Base(os.Args[0]))
options.PrintDefaults()
},
}
options.String("output", "static.go", "the generated output file path")
options.String("pkgname", "main", "the package name to use in the generated output")
options.String("funcname", "resources", "the function name to use in the generated output")
options.Bool("main", false, "whether to generate a main func or not")
if err := options.Parse(os.Args[1:]); err != nil {
os.Exit(1)
}
if options.NArg() == 0 {
options.Usage()
os.Exit(1)
}
if options.Lookup("main").Value.String() == "true" {
usemain = true
}
rpack.Pack(options.Arg(0), options.Lookup("output").Value.String(), options.Lookup("pkgname").Value.String(), options.Lookup("funcname").Value.String(), usemain)
}

155
vendor/github.com/pyke369/golang-support/rpack/rpack.go generated vendored Normal file
View File

@@ -0,0 +1,155 @@
package rpack
import (
"bytes"
"compress/gzip"
"crypto/md5"
"encoding/base64"
"fmt"
"io/ioutil"
"math/rand"
"mime"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"time"
)
type RPACK struct {
Compressed bool
Modified int64
Mime string
Content string
raw []byte
}
var guzpool = sync.Pool{
New: func() interface{} {
return &gzip.Reader{}
}}
func Pack(root, output, pkgname, funcname string, main bool) {
root = strings.TrimSuffix(root, "/")
if root == "" || output == "" {
return
}
if pkgname == "" || main {
pkgname = "main"
}
if funcname == "" {
funcname = "resources"
}
funcname = strings.ToUpper(funcname[:1]) + funcname[1:]
entries := map[string]*RPACK{}
compressor, _ := gzip.NewWriterLevel(nil, gzip.BestCompression)
count := 0
size := int64(0)
start := time.Now()
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
rpath := strings.TrimPrefix(path, root+"/")
if info.Mode()&os.ModeType == 0 {
for _, part := range strings.Split(rpath, "/") {
if len(part) > 0 && part[0] == '.' {
return nil
}
}
pack := &RPACK{Modified: info.ModTime().Unix(), Mime: "text/plain"}
if mime := mime.TypeByExtension(filepath.Ext(rpath)); mime != "" {
pack.Mime = mime
}
content, _ := ioutil.ReadFile(path)
compressed := bytes.Buffer{}
compressor.Reset(&compressed)
compressor.Write(content)
compressor.Close()
if compressed.Len() < len(content) {
pack.Content = base64.StdEncoding.EncodeToString(compressed.Bytes())
pack.Compressed = true
} else {
pack.Content = base64.StdEncoding.EncodeToString(content)
}
entries[rpath] = pack
fmt.Fprintf(os.Stderr, "\r%-120.120s ", rpath)
count++
size += info.Size()
}
return nil
})
fmt.Fprintf(os.Stderr, "\r%-120.120s\rpacked %d file(s) %d byte(s) in %v\n", "", count, size, time.Now().Sub(start))
if handle, err := os.OpenFile(output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err == nil {
random := make([]byte, 64)
rand.Seed(time.Now().UnixNano() + int64(os.Getpid()))
rand.Read(random)
uid := fmt.Sprintf("rpack%8.8x", md5.Sum(random))
fmt.Fprintf(handle,
`package %s
import (
"net/http"
"github.com/pyke369/golang-support/rpack"
)
var %s map[string]*rpack.RPACK = map[string]*rpack.RPACK {
`,
pkgname, uid)
for path, entry := range entries {
fmt.Fprintf(handle,
` "%s": &rpack.RPACK{Compressed:%t, Modified:%d, Mime:"%s", Content:"%s"},
`, path, entry.Compressed, entry.Modified, entry.Mime, entry.Content)
}
fmt.Fprintf(handle,
`}
func %s() http.Handler {
return rpack.Serve(%s)
}
`, funcname, uid)
if main {
fmt.Fprintf(handle,
`
func main() {
http.Handle("/resources/", http.StripPrefix("/resources/", %s()))
http.ListenAndServe(":8000", nil)
}
`, funcname)
}
handle.Close()
}
}
func Serve(pack map[string]*RPACK) http.Handler {
return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
var err error
if pack == nil || pack[request.URL.Path] == nil {
response.WriteHeader(http.StatusNotFound)
return
}
if pack[request.URL.Path].raw == nil {
if pack[request.URL.Path].raw, err = base64.StdEncoding.DecodeString(pack[request.URL.Path].Content); err != nil {
response.WriteHeader(http.StatusNotFound)
return
}
}
resource := pack[request.URL.Path]
response.Header().Set("Content-Type", resource.Mime)
if strings.Index(request.Header.Get("Accept-Encoding"), "gzip") >= 0 && request.Header.Get("Range") == "" && resource.Compressed {
response.Header().Set("Content-Encoding", "gzip")
response.Header().Set("Content-Length", fmt.Sprintf("%d", len(resource.raw)))
http.ServeContent(response, request, request.URL.Path, time.Unix(resource.Modified, 0), bytes.NewReader(resource.raw))
} else {
if resource.Compressed {
decompressor := guzpool.Get().(*gzip.Reader)
decompressor.Reset(bytes.NewReader(resource.raw))
if raw, err := ioutil.ReadAll(decompressor); err == nil {
http.ServeContent(response, request, request.URL.Path, time.Unix(resource.Modified, 0), bytes.NewReader(raw))
}
decompressor.Close()
guzpool.Put(decompressor)
} else {
http.ServeContent(response, request, request.URL.Path, time.Unix(resource.Modified, 0), bytes.NewReader(resource.raw))
}
}
})
}