bfile/resource/main.go

158 lines
3.5 KiB
Go
Raw Permalink Normal View History

2023-11-05 04:13:02 +01:00
package main
import (
"log"
2023-11-05 04:50:53 +01:00
"fmt"
"regexp"
"strings"
2023-11-05 05:09:30 +01:00
"net/http"
2023-11-05 04:13:02 +01:00
"io/ioutil"
)
import (
"github.com/BurntSushi/toml"
"github.com/gofiber/fiber/v2"
"github.com/dustin/go-humanize"
2023-11-05 04:13:02 +01:00
)
type Resource struct {
2023-11-05 05:09:30 +01:00
Url string `toml:"url"`
Proxied bool `toml:"proxied",default:false`
Mime string `toml:"mime"`
2023-11-05 04:13:02 +01:00
}
2023-11-05 04:36:24 +01:00
func (self Resource) Get() ([]byte, error) {
return ioutil.ReadFile(self.Url[7:])
}
2023-11-05 04:13:02 +01:00
type ResourceDConfig struct {
Enabled bool `toml:"enabled"`
ListenURL string `toml:"listen_url"`
ProxyCacheMinSize string `toml:"proxy_cache_min_size",default:5MB`
2023-11-05 04:13:02 +01:00
}
type Config struct {
ResourceD ResourceDConfig `toml:"resourceD"`
Resource map[string]Resource `toml:"resource"`
}
2023-11-05 04:50:53 +01:00
func (self Config) Validate() int {
re, err := regexp.Compile(`^(file|http(s|))://`)
if err != nil { panic(err) }
for key, res := range self.Resource {
if ! re.MatchString(res.Url) {
panic(fmt.Sprintf("Resource %s has invalid URL: %s\nOnly file://, http:// and https:// URLs are allowed", key, res.Url))
}
}
return 0
}
2023-11-05 06:05:30 +01:00
func (self Resource) GetProxied() ([]byte, error) {
cached, exists := ProxyResourceCache[self.Url];
if exists {
return cached, nil
}
resp, err := http.Get(self.Url)
if err != nil { return make([]byte, 0, 0), err }
buf, err := ioutil.ReadAll(resp.Body)
if err != nil { return make([]byte, 0, 0), err }
// cache only those that are less than 5 mb
if len(buf) > ProxyCacheMinSize {
ProxyResourceCache[self.Url] = buf
}
2023-11-05 06:05:30 +01:00
return buf, nil
}
var ProxyResourceCache map[string][]byte = make(map[string][]byte)
var ProxyCacheMinSize int
2023-11-05 04:50:53 +01:00
2023-11-05 04:13:02 +01:00
func main() {
var conf Config
data, err := ioutil.ReadFile("resourced.toml")
if err != nil { panic(err) }
a, err := toml.Decode(string(data), &conf)
if err != nil { panic(err) }
_ = a
2023-11-05 04:50:53 +01:00
cache_min, err := humanize.ParseBytes(conf.ResourceD.ProxyCacheMinSize)
if err != nil { panic(err) }
ProxyCacheMinSize = int(cache_min)
2023-11-05 04:50:53 +01:00
conf.Validate()
if len(conf.Resource) == 0 {
fmt.Println("\x1b[33m[warn] No resources are specified\x1b[0m");
} else {
fmt.Println(fmt.Sprintf("[info] Loaded %d resources", len(conf.Resource)))
}
if ! conf.ResourceD.Enabled {
fmt.Println("\x1b[33m[warn] resourceD is disabled. No resources will be served\x1b[0m")
}
2023-11-05 04:13:02 +01:00
2023-11-05 04:36:24 +01:00
app := fiber.New(fiber.Config {
Prefork: true,
CaseSensitive: false,
StrictRouting: true,
ServerHeader: "",
AppName: "blek! File resourceD",
})
2023-11-05 04:13:02 +01:00
app.Get("/info/is_enabled", func (c *fiber.Ctx) error {
return c.JSON(conf.ResourceD.Enabled)
})
2023-11-05 04:36:24 +01:00
app.Use(func (c *fiber.Ctx) error {
2023-11-05 04:13:02 +01:00
if ! conf.ResourceD.Enabled {
2023-11-05 04:36:24 +01:00
return c.Status(fiber.StatusNotFound).SendString("ResourceD is disabled")
2023-11-05 04:13:02 +01:00
}
2023-11-05 04:36:24 +01:00
return c.Next()
})
app.Get("/:id", func (c *fiber.Ctx) error {
2023-11-05 04:13:02 +01:00
res, exists := conf.Resource[c.Params("id")]
if ! exists {
return c.Status(fiber.StatusNotFound).SendString("Resource not found")
}
2023-11-05 04:50:53 +01:00
if ! strings.HasPrefix(res.Url, "file://") {
2023-11-05 05:09:30 +01:00
if res.Proxied {
2023-11-05 06:05:30 +01:00
data, err := res.GetProxied()
2023-11-05 05:09:30 +01:00
if err != nil {
log.Fatalln(err)
2023-11-05 06:05:30 +01:00
// we failed, send a redirect instead
2023-11-05 06:49:44 +01:00
// the next line would be the one with
// c.Location(res.Url)
2023-11-05 05:09:30 +01:00
} else {
c.Response().Header.SetContentType(res.Mime)
2023-11-05 06:05:30 +01:00
c.Response().Header.SetContentLength(len(data))
return c.Send(data)
2023-11-05 05:09:30 +01:00
}
}
2023-11-05 04:50:53 +01:00
c.Location(res.Url)
c.Status(302)
return nil
}
2023-11-05 04:36:24 +01:00
data, err := res.Get()
if err != nil {
panic(err)
}
c.Response().Header.SetContentType(res.Mime)
c.Response().Header.SetContentLength(len(data))
2023-11-05 04:50:53 +01:00
2023-11-05 04:36:24 +01:00
return c.Send(data)
2023-11-05 04:13:02 +01:00
})
log.Fatal(app.Listen(conf.ResourceD.ListenURL))
}