mirror of
https://github.com/woodchen-ink/webp_server_go.git
synced 2025-07-18 21:52:01 +08:00
Merge pull request #24 from webp-sh/add-log-level
Add custom log level, unsupported file returns
This commit is contained in:
commit
e8e12ee10c
@ -6,7 +6,6 @@ go:
|
|||||||
arch:
|
arch:
|
||||||
- amd64
|
- amd64
|
||||||
- arm64
|
- arm64
|
||||||
- ppc64le
|
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- windows
|
- windows
|
||||||
|
20
encoder.go
20
encoder.go
@ -3,21 +3,24 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"github.com/chai2010/webp"
|
|
||||||
"golang.org/x/image/bmp"
|
|
||||||
"image"
|
"image"
|
||||||
"image/gif"
|
"image/gif"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/chai2010/webp"
|
||||||
|
"golang.org/x/image/bmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WebpEncoder(p1, p2 string, quality float32, Log bool, c chan int) (err error) {
|
func WebpEncoder(p1, p2 string, quality float32, Log bool, c chan int) (err error) {
|
||||||
// if convert fails, return error; success nil
|
// if convert fails, return error; success nil
|
||||||
|
|
||||||
|
log.Debugf("target: %s with quality of %f", path.Base(p1), quality)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
var img image.Image
|
var img image.Image
|
||||||
|
|
||||||
@ -36,30 +39,31 @@ func WebpEncoder(p1, p2 string, quality float32, Log bool, c chan int) (err erro
|
|||||||
img, _ = bmp.Decode(bytes.NewReader(data))
|
img, _ = bmp.Decode(bytes.NewReader(data))
|
||||||
} else if strings.Contains(contentType, "gif") {
|
} else if strings.Contains(contentType, "gif") {
|
||||||
// TODO: need to support animated webp
|
// TODO: need to support animated webp
|
||||||
|
log.Warn("Gif support is not perfect!")
|
||||||
img, _ = gif.Decode(bytes.NewReader(data))
|
img, _ = gif.Decode(bytes.NewReader(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
if img == nil {
|
if img == nil {
|
||||||
msg := "image file " + path.Base(p1) + " is corrupted or not supported"
|
msg := "image file " + path.Base(p1) + " is corrupted or not supported"
|
||||||
log.Println(msg)
|
log.Debug(msg)
|
||||||
err = errors.New(msg)
|
err = errors.New(msg)
|
||||||
ChanErr(c)
|
ChanErr(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = webp.Encode(&buf, img, &webp.Options{Lossless: false, Quality: quality}); err != nil {
|
if err = webp.Encode(&buf, img, &webp.Options{Lossless: false, Quality: quality}); err != nil {
|
||||||
log.Println(err)
|
log.Error(err)
|
||||||
ChanErr(c)
|
ChanErr(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = ioutil.WriteFile(p2, buf.Bytes(), 0755); err != nil {
|
if err = ioutil.WriteFile(p2, buf.Bytes(), 0755); err != nil {
|
||||||
log.Println(err)
|
log.Error(err)
|
||||||
ChanErr(c)
|
ChanErr(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Log {
|
if Log {
|
||||||
fmt.Printf("Save to %s ok\n", p2)
|
log.Info("Save to " + p2 + " ok!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
ChanErr(c)
|
ChanErr(c)
|
||||||
|
1
go.mod
1
go.mod
@ -5,5 +5,6 @@ go 1.13
|
|||||||
require (
|
require (
|
||||||
github.com/chai2010/webp v1.1.0
|
github.com/chai2010/webp v1.1.0
|
||||||
github.com/gofiber/fiber v1.4.0
|
github.com/gofiber/fiber v1.4.0
|
||||||
|
github.com/sirupsen/logrus v1.4.2
|
||||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1
|
||||||
)
|
)
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -38,6 +39,7 @@ func ImageExists(filename string) bool {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
log.Debugf("file %s exists!", filename)
|
||||||
return !info.IsDir()
|
return !info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ func GenWebpAbs(RawImagePath string, ExhaustPath string, ImgFilename string, req
|
|||||||
// get file mod time
|
// get file mod time
|
||||||
STAT, err := os.Stat(RawImagePath)
|
STAT, err := os.Stat(RawImagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Error(err.Error())
|
||||||
}
|
}
|
||||||
ModifiedTime := STAT.ModTime().Unix()
|
ModifiedTime := STAT.ModTime().Unix()
|
||||||
// webpFilename: abc.jpg.png -> abc.jpg.png1582558990.webp
|
// webpFilename: abc.jpg.png -> abc.jpg.png1582558990.webp
|
||||||
|
11
prefetch.go
11
prefetch.go
@ -3,20 +3,23 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func PrefetchImages(confImgPath string, ExhaustPath string, QUALITY string) {
|
func PrefetchImages(confImgPath string, ExhaustPath string, QUALITY string) {
|
||||||
fmt.Println(`Prefetch will convert all your images to webp, it may take some time and consume a lot of CPU resource. Do you want to proceed(Y/n)`)
|
fmt.Println(`Prefetch will convert all your images to webp,
|
||||||
|
it may take some time and consume a lot of CPU resource. Do you want to proceed(Y/n)`)
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
char, _, _ := reader.ReadRune() //y Y enter
|
char, _, _ := reader.ReadRune() //y Y enter
|
||||||
// maximum ongoing prefetch is depending on your core of CPU
|
// maximum ongoing prefetch is depending on your core of CPU
|
||||||
log.Printf("Prefetching using %d cores", jobs)
|
log.Infof("Prefetching using %d cores", jobs)
|
||||||
var finishChan = make(chan int, jobs)
|
var finishChan = make(chan int, jobs)
|
||||||
for i := 0; i < jobs; i++ {
|
for i := 0; i < jobs; i++ {
|
||||||
finishChan <- 0
|
finishChan <- 0
|
||||||
@ -42,7 +45,7 @@ func PrefetchImages(confImgPath string, ExhaustPath string, QUALITY string) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Debug(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
router.go
27
router.go
@ -1,13 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/gofiber/fiber"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY string) func(c *fiber.Ctx) {
|
func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY string) func(c *fiber.Ctx) {
|
||||||
@ -21,9 +22,11 @@ func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY
|
|||||||
UA := c.Get("User-Agent")
|
UA := c.Get("User-Agent")
|
||||||
if strings.Contains(UA, "Safari") && !strings.Contains(UA, "Chrome") &&
|
if strings.Contains(UA, "Safari") && !strings.Contains(UA, "Chrome") &&
|
||||||
!strings.Contains(UA, "Firefox") {
|
!strings.Contains(UA, "Firefox") {
|
||||||
|
log.Info("A Safari use has arrived...")
|
||||||
c.SendFile(RawImageAbs)
|
c.SendFile(RawImageAbs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Debugf("Incoming connection from %s@%s with %s", UA, c.IP(), ImgFilename)
|
||||||
|
|
||||||
// check ext
|
// check ext
|
||||||
// TODO: may remove this function. Check in Nginx.
|
// TODO: may remove this function. Check in Nginx.
|
||||||
@ -39,19 +42,25 @@ func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !allowed {
|
if !allowed {
|
||||||
c.Send("File extension not allowed!")
|
msg := "File extension not allowed! " + ImgFilename
|
||||||
c.SendStatus(403)
|
log.Warn(msg)
|
||||||
|
c.Send(msg)
|
||||||
|
if ImageExists(RawImageAbs) {
|
||||||
|
c.SendFile(RawImageAbs)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the original image for existence,
|
// Check the original image for existence,
|
||||||
if !ImageExists(RawImageAbs) {
|
if !ImageExists(RawImageAbs) {
|
||||||
c.Send("Image not found!")
|
msg := "Image not found!"
|
||||||
|
c.Send(msg)
|
||||||
|
log.Warn(msg)
|
||||||
c.SendStatus(404)
|
c.SendStatus(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cwd, WebpAbsPath := GenWebpAbs(RawImageAbs, ExhaustPath, ImgFilename, reqURI)
|
_, WebpAbsPath := GenWebpAbs(RawImageAbs, ExhaustPath, ImgFilename, reqURI)
|
||||||
|
|
||||||
if ImageExists(WebpAbsPath) {
|
if ImageExists(WebpAbsPath) {
|
||||||
finalFile = WebpAbsPath
|
finalFile = WebpAbsPath
|
||||||
@ -59,10 +68,10 @@ func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY
|
|||||||
// we don't have abc.jpg.png1582558990.webp
|
// we don't have abc.jpg.png1582558990.webp
|
||||||
// delete the old pic and convert a new one.
|
// delete the old pic and convert a new one.
|
||||||
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558990.webp
|
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558990.webp
|
||||||
destHalfFile := path.Clean(path.Join(cwd, "exhaust", path.Dir(reqURI), ImgFilename))
|
destHalfFile := path.Clean(path.Join(WebpAbsPath, path.Dir(reqURI), ImgFilename))
|
||||||
matches, err := filepath.Glob(destHalfFile + "*")
|
matches, err := filepath.Glob(destHalfFile + "*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Error(err.Error())
|
||||||
} else {
|
} else {
|
||||||
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558100.webp <- older ones will be removed
|
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558100.webp <- older ones will be removed
|
||||||
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558990.webp <- keep the latest one
|
// /home/webp_server/exhaust/path/to/tsuki.jpg.1582558990.webp <- keep the latest one
|
||||||
@ -79,7 +88,7 @@ func Convert(ImgPath string, ExhaustPath string, AllowedTypes []string, QUALITY
|
|||||||
err = WebpEncoder(RawImageAbs, WebpAbsPath, float32(q), true, nil)
|
err = WebpEncoder(RawImageAbs, WebpAbsPath, float32(q), true, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
log.Error(err)
|
||||||
c.SendStatus(400)
|
c.SendStatus(400)
|
||||||
c.Send("Bad file!")
|
c.Send("Bad file!")
|
||||||
return
|
return
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Name: webp-server
|
Name: webp-server
|
||||||
Version: 0.0.4
|
Version: 0.1.1
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Go version of WebP Server. A tool that will serve your JPG/PNGs as WebP format with compression, on-the-fly.
|
Summary: Go version of WebP Server. A tool that will serve your JPG/PNGs as WebP format with compression, on-the-fly.
|
||||||
|
|
||||||
|
18
update.go
18
update.go
@ -4,17 +4,18 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func autoUpdate() {
|
func autoUpdate() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Println("Download error.", err)
|
log.Error("Download error.", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -23,16 +24,16 @@ func autoUpdate() {
|
|||||||
TagName string `json:"tag_name"`
|
TagName string `json:"tag_name"`
|
||||||
}
|
}
|
||||||
var res Result
|
var res Result
|
||||||
|
log.Debugf("Requesting to %s", api)
|
||||||
resp1, _ := http.Get(api)
|
resp1, _ := http.Get(api)
|
||||||
data1, _ := ioutil.ReadAll(resp1.Body)
|
data1, _ := ioutil.ReadAll(resp1.Body)
|
||||||
_ = json.Unmarshal(data1, &res)
|
_ = json.Unmarshal(data1, &res)
|
||||||
|
|
||||||
var gitVersion = res.TagName
|
var gitVersion = res.TagName
|
||||||
|
|
||||||
if gitVersion > version {
|
if gitVersion > version {
|
||||||
log.Printf("Time to update! New version %s found!", gitVersion)
|
log.Infof("Time to update! New version %s found", gitVersion)
|
||||||
} else {
|
} else {
|
||||||
log.Println("No new version found.")
|
log.Debug("No new version found.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,11 +42,10 @@ func autoUpdate() {
|
|||||||
filename += ".exe"
|
filename += ".exe"
|
||||||
}
|
}
|
||||||
var releaseUrl = "https://github.com/webp-sh/webp_server_go/releases/latest/download/" + filename
|
var releaseUrl = "https://github.com/webp-sh/webp_server_go/releases/latest/download/" + filename
|
||||||
log.Println("Downloading binary...")
|
log.Info("Downloading binary to update...")
|
||||||
resp, _ := http.Get(releaseUrl)
|
resp, _ := http.Get(releaseUrl)
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
log.Printf("%s-%s not found on release. "+
|
log.Debug("%s-%s not found on release.", runtime.GOOS, runtime.GOARCH)
|
||||||
"Contact developers to supply your version", runtime.GOOS, runtime.GOARCH)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, _ := ioutil.ReadAll(resp.Body)
|
data, _ := ioutil.ReadAll(resp.Body)
|
||||||
@ -54,7 +54,7 @@ func autoUpdate() {
|
|||||||
err := ioutil.WriteFile(path.Join("update", filename), data, 0755)
|
err := ioutil.WriteFile(path.Join("update", filename), data, 0755)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Println("Update complete. Please find your binary from update directory.")
|
log.Info("Update complete. Please find your binary from update directory.")
|
||||||
}
|
}
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/gofiber/fiber"
|
"github.com/gofiber/fiber"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -21,13 +21,14 @@ type Config struct {
|
|||||||
ExhaustPath string `json:"EXHAUST_PATH"`
|
ExhaustPath string `json:"EXHAUST_PATH"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = "0.1.0"
|
const version = "0.1.1"
|
||||||
|
|
||||||
var configPath string
|
var configPath string
|
||||||
var prefetch bool
|
var prefetch bool
|
||||||
var jobs int
|
var jobs int
|
||||||
var dumpConfig bool
|
var dumpConfig bool
|
||||||
var dumpSystemd bool
|
var dumpSystemd bool
|
||||||
|
var verboseMode bool
|
||||||
|
|
||||||
const sampleConfig = `
|
const sampleConfig = `
|
||||||
{
|
{
|
||||||
@ -36,7 +37,7 @@ const sampleConfig = `
|
|||||||
"QUALITY": "80",
|
"QUALITY": "80",
|
||||||
"IMG_PATH": "/path/to/pics",
|
"IMG_PATH": "/path/to/pics",
|
||||||
"EXHAUST_PATH": "",
|
"EXHAUST_PATH": "",
|
||||||
"ALLOWED_TYPES": ["jpg","png","jpeg","bmp","gif"]
|
"ALLOWED_TYPES": ["jpg","png","jpeg","bmp"]
|
||||||
}`
|
}`
|
||||||
const sampleSystemd = `
|
const sampleSystemd = `
|
||||||
[Unit]
|
[Unit]
|
||||||
@ -54,7 +55,6 @@ ExecReload=/bin/kill -HUP $MAINPID
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=3s
|
RestartSec=3s
|
||||||
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target`
|
WantedBy=multi-user.target`
|
||||||
|
|
||||||
@ -67,6 +67,11 @@ func loadConfig(path string) Config {
|
|||||||
defer jsonObject.Close()
|
defer jsonObject.Close()
|
||||||
decoder := json.NewDecoder(jsonObject)
|
decoder := json.NewDecoder(jsonObject)
|
||||||
_ = decoder.Decode(&config)
|
_ = decoder.Decode(&config)
|
||||||
|
_, err = os.Stat(config.ImgPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Your image path %s is incorrect.Please check and confirm.", config.ImgPath)
|
||||||
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +81,27 @@ func init() {
|
|||||||
flag.IntVar(&jobs, "jobs", runtime.NumCPU(), "Prefetch thread, default is all.")
|
flag.IntVar(&jobs, "jobs", runtime.NumCPU(), "Prefetch thread, default is all.")
|
||||||
flag.BoolVar(&dumpConfig, "dump-config", false, "Print sample config.json")
|
flag.BoolVar(&dumpConfig, "dump-config", false, "Print sample config.json")
|
||||||
flag.BoolVar(&dumpSystemd, "dump-systemd", false, "Print sample systemd service file.")
|
flag.BoolVar(&dumpSystemd, "dump-systemd", false, "Print sample systemd service file.")
|
||||||
|
flag.BoolVar(&verboseMode, "v", false, "Verbose, print out debug info.")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
// Logrus
|
||||||
|
log.SetOutput(os.Stdout)
|
||||||
|
log.SetReportCaller(true)
|
||||||
|
Formatter := &log.TextFormatter{
|
||||||
|
EnvironmentOverrideColors: true,
|
||||||
|
FullTimestamp: true,
|
||||||
|
TimestampFormat: "2006-01-02 15:04:05",
|
||||||
|
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
|
||||||
|
return fmt.Sprintf("[%s()]", f.Function), ""
|
||||||
|
},
|
||||||
|
}
|
||||||
|
log.SetFormatter(Formatter)
|
||||||
|
|
||||||
|
if verboseMode {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
log.Debug("Debug mode is enable!")
|
||||||
|
} else {
|
||||||
|
log.SetLevel(log.InfoLevel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -116,8 +141,7 @@ func main() {
|
|||||||
ListenAddress := HOST + ":" + PORT
|
ListenAddress := HOST + ":" + PORT
|
||||||
|
|
||||||
// Server Info
|
// Server Info
|
||||||
ServerInfo := "WebP Server " + version + " is running at " + ListenAddress
|
log.Infof("WebP Server %s %s", version, ListenAddress)
|
||||||
fmt.Println(ServerInfo)
|
|
||||||
|
|
||||||
app.Get("/*", Convert(confImgPath, ExhaustPath, AllowedTypes, QUALITY))
|
app.Get("/*", Convert(confImgPath, ExhaustPath, AllowedTypes, QUALITY))
|
||||||
app.Listen(ListenAddress)
|
app.Listen(ListenAddress)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user