CI and minor fixes

* use GitHub Actions as CI
* bump versions
* Makefile and Dockerfile improvements
* upgrade logrus
This commit is contained in:
BennyThink 2021-12-04 22:52:44 +08:00
parent 7c65d5e213
commit 67d40b4397
No known key found for this signature in database
GPG Key ID: 6CD0DBDA5235D481
15 changed files with 168 additions and 180 deletions

9
.dockerignore Normal file
View File

@ -0,0 +1,9 @@
.github/*
exhaust/*
pics/*
remote-raw/*
scripts/*
.git/*
README.md
LICENSE
Makefile

21
.github/workflows/CI.yaml vendored Normal file
View File

@ -0,0 +1,21 @@
name: CI
on:
push:
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.17.3
- name: run test cases
run: sudo apt install libaom-dev && make test && make

View File

@ -1,16 +1,16 @@
FROM golang:alpine as builder
FROM golang:1.17.4-alpine as builder
ARG IMG_PATH=/opt/pics
ARG EXHAUST_PATH=/opt/exhaust
RUN apk update && apk add alpine-sdk && mkdir /build
RUN apk update && apk add alpine-sdk aom-dev && mkdir /build
COPY go.mod /build
RUN cd /build && go mod download
COPY . /build
RUN cd /build && sed -i "s|.\/pics|${IMG_PATH}|g" config.json \
&& sed -i "s|\"\"|\"${EXHAUST_PATH}\"|g" config.json \
&& sed -i 's/127.0.0.1/0.0.0.0/g' config.json \
&& make docker
RUN cd /build && sed -i "s|.\/pics|${IMG_PATH}|g" config.json \
&& sed -i "s|\"\"|\"${EXHAUST_PATH}\"|g" config.json \
&& sed -i 's/127.0.0.1/0.0.0.0/g' config.json \
&& go build -ldflags="-s -w" -o webp-server .

View File

@ -14,6 +14,7 @@ default:
make clean
go build -o builds/webp-server-$(OS)-$(ARCH) .
ls builds
all:
make clean
./scripts/build.sh $(OS) $(ARCH)
@ -26,4 +27,4 @@ clean:
rm -rf prefetch
docker:
go build -ldflags="-s -w" -o webp-server .
DOCKER_BUILDKIT=1 docker build -t webpsh/webps .

View File

@ -21,7 +21,7 @@ var (
prefetch, proxyMode bool
remoteRaw = "remote-raw"
config Config
version = "0.3.2"
version = "0.4.0"
releaseUrl = "https://github.com/webp-sh/webp_server_go/releases/latest/download/"
)

View File

@ -81,8 +81,7 @@ func readRawImage(imgPath string, maxPixel int) (img image.Image, err error) {
} else if strings.Contains(contentType, "bmp") {
img, err = bmp.Decode(bytes.NewReader(data))
}
if err != nil {
if err != nil || img == nil {
errinfo := fmt.Sprintf("image file %s is corrupted: %v", imgPath, err)
log.Errorln(errinfo)
return nil, errors.New(errinfo)

View File

@ -4,64 +4,63 @@ import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"
)
func walker() []string {
var list []string
_ = filepath.Walk("./pics", func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
list = append(list, path)
_ = filepath.Walk("./pics", func(p string, info os.FileInfo, err error) error {
if !info.IsDir() && !strings.HasPrefix(path.Base(p), ".") {
list = append(list, p)
}
return nil
})
return list
}
func TestWebpEncoder(t *testing.T) {
var webp = "/tmp/test-result.webp"
func TestWebPEncoder(t *testing.T) {
// Go through every files
var dest = "/tmp/test-result"
var target = walker()
for _, f := range target {
//fmt.Println(b, c, webp)
runEncoder(t, f, webp)
runEncoder(t, f, dest)
}
_ = os.Remove(webp)
_ = os.Remove(dest)
}
// test error
err := webpEncoder("./pics/empty.jpg", webp, 80)
assert.NotNil(t, err)
_ = os.Remove(webp)
func TestAvifEncoder(t *testing.T) {
// Only one file: img_over_16383px.jpg might cause memory issues on CI environment
var dest = "/tmp/test-result"
avifEncoder("./pics/big.jpg", dest, 80)
assertType(t, dest, "image/avif")
}
func TestNonExistImage(t *testing.T) {
var webp = "/tmp/test-result.webp"
// test error
var err = webpEncoder("./pics/empty.jpg", webp, 80)
assert.NotNil(t, err)
_ = os.Remove(webp)
var dest = "/tmp/test-result"
webpEncoder("./pics/empty.jpg", dest, 80)
avifEncoder("./pics/empty.jpg", dest, 80)
}
func TestConvertFail(t *testing.T) {
var webp = "/tmp/test-result.webp"
var err = webpEncoder("./pics/webp_server.jpg", webp, -1)
assert.NotNil(t, t, err)
var dest = "/tmp/test-result"
webpEncoder("./pics/webp_server.jpg", dest, -1)
avifEncoder("./pics/webp_server.jpg", dest, -1)
}
func runEncoder(t *testing.T, file string, webp string) {
//t.Logf("convert from %s to %s", file, webp)
var err = webpEncoder(file, webp, 80)
if file == "pics/empty.jpg" && err != nil {
func runEncoder(t *testing.T, file string, dest string) {
if file == "pics/empty.jpg" {
t.Log("Empty file, that's okay.")
} else if err != nil {
t.Fatalf("Fatal, convert failed for %s: %v ", file, err)
}
data, _ := ioutil.ReadFile(webp)
types := getFileContentType(data[:512])
if types != "image/webp" {
t.Fatal("Fatal, file type is wrong!")
}
webpEncoder(file, dest, 80)
assertType(t, dest, "image/webp")
}
func assertType(t *testing.T, dest, mime string) {
data, _ := ioutil.ReadFile(dest)
types := getFileContentType(data[:512])
assert.Equalf(t, mime, types, "File %s should be %s", dest, mime)
}

4
go.mod
View File

@ -7,12 +7,14 @@ require (
github.com/chai2010/webp v1.1.0
github.com/gofiber/fiber/v2 v2.4.0
github.com/h2non/filetype v1.1.3
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
github.com/schollz/progressbar/v3 v3.8.3
github.com/sirupsen/logrus v1.6.0
github.com/sirupsen/logrus v1.8.1
github.com/staktrace/go-update v0.0.0-20210525161054-fc019945f9a2
github.com/stretchr/testify v1.3.0
github.com/valyala/fasthttp v1.18.0
golang.org/x/image v0.0.0-20200119044424-58c23975cae1
golang.org/x/sys v0.0.0-20211204120058-94396e421777 // indirect
)
replace (

5
go.sum
View File

@ -25,6 +25,8 @@ github.com/schollz/progressbar/v3 v3.8.3 h1:FnLGl3ewlDUP+YdSwveXBaXs053Mem/du+wr
github.com/schollz/progressbar/v3 v3.8.3/go.mod h1:pWnVCjSBZsT2X3nx9HfRdnCDrpbevliMeoEVhStwHko=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/staktrace/go-update v0.0.0-20210525161054-fc019945f9a2 h1:kyTDvRL8TyTHOx0aK1PKMPVfkI7rCLDC1nrKF7SYOBc=
github.com/staktrace/go-update v0.0.0-20210525161054-fc019945f9a2/go.mod h1:yzHsbjWRHVF1vVGsluwqCc2TvogFSx9C8TeBh34cMb0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -53,6 +55,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -60,6 +63,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211204120058-94396e421777 h1:QAkhGVjOxMa+n4mlsAWeAU+BMZmimQAaNiMu+iUi94E=
golang.org/x/sys v0.0.0-20211204120058-94396e421777/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -1,31 +1,33 @@
package main
import (
log "github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
"io/ioutil"
"net/http"
"path/filepath"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
// test this file: go test -v -cover .
// test all files: go test -v -cover .
// test one case: go test -v -run TestSelectFormat
func TestGetFileContentType(t *testing.T) {
var data = []byte("hello")
var expected = "text/plain; charset=utf-8"
var data = []byte("remember remember the 5th of november")
var expected = ""
var result = getFileContentType(data)
assert.Equalf(t, result, expected, "Result: [%s], Expected: [%s]", result, expected)
}
func TestFileCount(t *testing.T) {
var data = ".github"
var expected = 2
var data = "scripts"
var expected int64 = 2
var result = fileCount(data)
assert.Equalf(t, result, expected, "Result: [%d], Expected: [%d]", result, expected)
}
func TestImageExists(t *testing.T) {
@ -71,108 +73,63 @@ func TestGenEtag(t *testing.T) {
}
func TestGoOrigin(t *testing.T) {
func TestSelectFormat(t *testing.T) {
// this is a complete test case for webp compatibility
// func goOrigin(header, ua string) bool
// UNLESS YOU KNOW WHAT YOU ARE DOING, DO NOT CHANGE THE TEST CASE MAPPING HERE.
var testCase = map[[2]string]bool{
var fullSupport = []string{"avif", "webp", "raw"}
var webpSupport = []string{"webp", "raw"}
var jpegSupport = []string{"raw"}
var testCase = map[[2]string][]string{
// Latest Chrome on Windows, macOS, linux, Android and iOS 13
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"}: fullSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"}: fullSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"}: fullSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.60 Mobile Safari/537.36"}: fullSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (Linux; Android 6.0; HTC M8t) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Mobile Safari/537.36"}: fullSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "HTCM8t_LTE/1.0 Android/4.4 release/2013 Browser/WAP2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 AppleWebKit/534.30"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/83.0.4103.63 Mobile/15E148 Safari/604.1"}: jpegSupport,
// macOS Catalina Safari
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Safari/605.1.15"}: true,
// macOS Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.88 Safari/537.36"}: false,
// iOS14 Safari
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1"}: false,
// iOS14 Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1"}: false,
// iPadOS 14 Safari
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1"}: false,
// iPadOS 14 Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1"}: false,
// Warning: these three are real capture headers - I don't have iOS/iPadOS prior to version 14
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}: true,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPad; CPU OS 10_15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/25.0 Mobile/15E148 Safari/605.1.15"}: true,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/83.0.4103.63 Mobile/15E148 Safari/604.1"}: true,
}
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Safari/605.1.15"}: jpegSupport,
for value, is := range testCase {
assert.Equalf(t, is, goOrigin(value[0], value[1]), "[%v]:[%s]", value, is)
}
}
// iOS14 Safari and Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1"}: webpSupport,
func TestUaOrigin(t *testing.T) {
// reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
// https://developer.chrome.com/multidevice/user-agent#chrome_for_ios_user_agent
// iPadOS 14 Safari and Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1"}: webpSupport,
// UNLESS YOU KNOW WHAT YOU ARE DOING, DO NOT CHANGE THE TEST CASE MAPPING HERE.
var testCase = map[string]bool{
// Chrome on Windows, macOS, linux, iOS and Android
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36": false,
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36": false,
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36": false,
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/83.0.4103.63 Mobile/15E148 Safari/604.1": true,
"Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.60 Mobile Safari/537.36": false,
// Firefox on Windows, macOS, linux, iOS and Android
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0": false,
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0": false,
"Mozilla/5.0 (X11; Linux i686; rv:76.0) Gecko/20100101 Firefox/76.0": false,
"Mozilla/5.0 (iPad; CPU OS 10_15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/25.0 Mobile/15E148 Safari/605.1.15": true,
"Mozilla/5.0 (Android 10; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0": false,
// Safari on macOS and iOS
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15": true,
"Mozilla/5.0 (iPad; CPU OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1": true,
// WeChat on iOS, Windows, and Android
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 wxwork/2.1.5 MicroMessenger/6.3.22": true,
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.691.400 QQBrowser/9.0.2524.400": false,
"Mozilla/5.0 (Linux; Android 7.0; LG-H831 Build/NRD90U; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36 MicroMessenger/6.6.7.1303(0x26060743) NetType/WIFI Language/zh_TW": false,
// iOS 15 Safari, Firefox and Chrome
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/39.0 Mobile/15E148 Safari/605.1.15"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/96.0.4664.53 Mobile/15E148 Safari/604.1"}: webpSupport,
// IE
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko": true,
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)": true,
[2]string{"application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"}: jpegSupport,
// Others
"PostmanRuntime/7.26.1": true,
"curl/7.64.1": true,
[2]string{"", "PostmanRuntime/7.26.1"}: jpegSupport,
[2]string{"", "curl/7.64.1"}: jpegSupport,
[2]string{"image/webp", "curl/7.64.1"}: webpSupport,
[2]string{"image/avif,image/webp", "curl/7.64.1"}: fullSupport,
// these four are captured from iOS14/iPadOS14, which supports webp
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1": false,
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1\n": false,
"Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1": false,
"Mozilla/5.0 (iPad; CPU OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1": false,
// some weird browsers
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.16(0x18001033) NetType/WIFI Language/zh_CN"}: webpSupport,
[2]string{"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Mozilla/5.0 (Linux; Android 6.0; HTC M8t Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.95 Mobile Safari/537.36 MMWEBID/4285 MicroMessenger/8.0.15.2001(0x28000F41) Process/tools WeChat/arm32 Weixin GPVersion/1 NetType/WIFI Language/zh_CN ABI/arm32"}: webpSupport,
}
for browser, expected := range testCase {
var header fasthttp.RequestHeader
header.Set("accept", browser[0])
header.Set("user-agent", browser[1])
guessed := guessSupportedFormat(&header)
sort.Strings(expected)
sort.Strings(guessed)
log.Infof("%s expected%s --- actual %s", browser, expected, guessed)
assert.Equal(t, expected, guessed)
}
for browser, is := range testCase {
assert.Equalf(t, is, uaOrigin(browser), "[%v]:[%s]", is, browser)
}
}
func TestHeaderOrigin(t *testing.T) {
// Chrome: Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8
// Safari 版本14.0.1 (15610.2.11.51.10, 15610): Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5
// Safari Technology Preview Release 116 (Safari 14.1, WebKit 15611.1.5.3) Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5
// UNLESS YOU KNOW WHAT YOU ARE DOING, DO NOT CHANGE THE TEST CASE MAPPING HERE.
var testCase = map[string]bool{
"image/avif,image/webp,image/apng,image/*,*/*;q=0.8": false,
"*/*": true,
"image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5": true,
"I don't know what it is:-)": true,
}
for header, is := range testCase {
assert.Equalf(t, is, headerOrigin(header), "[%v]:[%s]", is, header)
}
}
func TestChanErr(t *testing.T) {
var value = 2
var testC = make(chan int, 2)
testC <- value
chanErr(testC)
value = <-testC
assert.Equal(t, 2, value)
}
func TestGetRemoteImageInfo(t *testing.T) {
@ -197,7 +154,7 @@ func TestFetchRemoteImage(t *testing.T) {
err := fetchRemoteImage(fp, url)
assert.Equal(t, err, nil)
data, _ := ioutil.ReadFile(fp)
assert.Equal(t, "image/x-icon", getFileContentType(data))
assert.Equal(t, "image/vnd.microsoft.icon", getFileContentType(data))
// test can't create file
err = fetchRemoteImage("/", url)

View File

@ -35,6 +35,7 @@ func prefetchImages(confImgPath string, ExhaustPath string) {
proposedURI := strings.Replace(picAbsPath, confImgPath, "", 1)
avif, webp := genOptimizedAbs(picAbsPath, ExhaustPath, info.Name(), proposedURI)
_ = os.MkdirAll(path.Dir(avif), 0755)
log.Infof("Prefetching %s", picAbsPath)
go convertFilter(picAbsPath, avif, webp, finishChan)
_ = bar.Add(<-finishChan)
return nil

View File

@ -11,24 +11,15 @@ import (
)
func TestPrefetchImages(t *testing.T) {
// single thread
fp := "./prefetch"
_ = os.Mkdir(fp, 0755)
prefetchImages("./pics", "./prefetch", "80")
prefetchImages("./pics/dir1/", "./prefetch")
count := fileCount("./prefetch")
assert.Equal(t, 8, count)
_ = os.RemoveAll(fp)
// concurrency
jobs = 2
_ = os.Mkdir(fp, 0755)
prefetchImages("./pics", "./prefetch", "80")
count = fileCount("./prefetch")
assert.Equal(t, 6, count)
assert.Equal(t, int64(2), count)
_ = os.RemoveAll(fp)
}
func TestBadPrefetch(t *testing.T) {
jobs = 1
prefetchImages("./pics2", "./prefetch", "80")
prefetchImages("./pics2", "./prefetch")
}

View File

@ -15,8 +15,10 @@ import (
)
var (
chromeUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36"
safariUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"
chromeUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36"
acceptWebP = "image/webp,image/apng,image/*,*/*;q=0.8"
acceptLegacy = "image/jpeg"
safariUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"
)
func setupParam() {
@ -29,10 +31,14 @@ func setupParam() {
remoteRaw = "remote-raw"
}
func requestToServer(url string, app *fiber.App, ua string) (*http.Response, []byte) {
func requestToServer(url string, app *fiber.App, ua, accept string) (*http.Response, []byte) {
req := httptest.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", ua)
resp, _ := app.Test(req, 60000)
req.Header.Set("Accept", accept)
resp, err := app.Test(req, 120000)
if err != nil {
return nil, nil
}
data, _ := ioutil.ReadAll(resp.Body)
return resp, data
}
@ -44,7 +50,7 @@ func TestServerHeaders(t *testing.T) {
url := "http://127.0.0.1:3333/webp_server.bmp"
// test for chrome
response, _ := requestToServer(url, app, chromeUA)
response, _ := requestToServer(url, app, chromeUA, acceptWebP)
ratio := response.Header.Get("X-Compression-Rate")
etag := response.Header.Get("Etag")
@ -52,7 +58,7 @@ func TestServerHeaders(t *testing.T) {
assert.NotEqual(t, "", etag)
// test for safari
response, _ = requestToServer(url, app, safariUA)
response, _ = requestToServer(url, app, safariUA, acceptLegacy)
ratio = response.Header.Get("X-Compression-Rate")
etag = response.Header.Get("Etag")
@ -66,9 +72,9 @@ func TestConvert(t *testing.T) {
"http://127.0.0.1:3333/webp_server.jpg": "image/webp",
"http://127.0.0.1:3333/webp_server.bmp": "image/webp",
"http://127.0.0.1:3333/webp_server.png": "image/webp",
"http://127.0.0.1:3333/empty.jpg": "text/plain; charset=utf-8",
"http://127.0.0.1:3333/empty.jpg": "",
"http://127.0.0.1:3333/png.jpg": "image/webp",
"http://127.0.0.1:3333/12314.jpg": "text/plain; charset=utf-8",
"http://127.0.0.1:3333/12314.jpg": "",
"http://127.0.0.1:3333/dir1/inside.jpg": "image/webp",
"http://127.0.0.1:3333/%e5%a4%aa%e7%a5%9e%e5%95%a6.png": "image/webp",
"http://127.0.0.1:3333/太神啦.png": "image/webp",
@ -78,9 +84,9 @@ func TestConvert(t *testing.T) {
"http://127.0.0.1:3333/webp_server.jpg": "image/jpeg",
"http://127.0.0.1:3333/webp_server.bmp": "image/bmp",
"http://127.0.0.1:3333/webp_server.png": "image/png",
"http://127.0.0.1:3333/empty.jpg": "text/plain; charset=utf-8",
"http://127.0.0.1:3333/empty.jpg": "",
"http://127.0.0.1:3333/png.jpg": "image/png",
"http://127.0.0.1:3333/12314.jpg": "text/plain; charset=utf-8",
"http://127.0.0.1:3333/12314.jpg": "",
"http://127.0.0.1:3333/dir1/inside.jpg": "image/jpeg",
}
@ -89,14 +95,14 @@ func TestConvert(t *testing.T) {
// test Chrome
for url, respType := range testChromeLink {
_, data := requestToServer(url, app, chromeUA)
_, data := requestToServer(url, app, chromeUA, acceptWebP)
contentType := getFileContentType(data)
assert.Equal(t, respType, contentType)
}
// test Safari
for url, respType := range testSafariLink {
_, data := requestToServer(url, app, safariUA)
_, data := requestToServer(url, app, safariUA, acceptLegacy)
contentType := getFileContentType(data)
assert.Equal(t, respType, contentType)
}
@ -112,13 +118,13 @@ func TestConvertNotAllowed(t *testing.T) {
// not allowed, but we have the file
url := "http://127.0.0.1:3333/webp_server.bmp"
_, data := requestToServer(url, app, chromeUA)
_, data := requestToServer(url, app, chromeUA, acceptWebP)
contentType := getFileContentType(data)
assert.Equal(t, "image/bmp", contentType)
// not allowed, random file
url = url + "hagdgd"
_, data = requestToServer(url, app, chromeUA)
_, data = requestToServer(url, app, chromeUA, acceptWebP)
assert.Contains(t, string(data), "File extension not allowed")
}
@ -132,7 +138,7 @@ func TestConvertProxyModeBad(t *testing.T) {
// this is local random image, should be 500
url := "http://127.0.0.1:3333/webp_8888server.bmp"
resp, _ := requestToServer(url, app, chromeUA)
resp, _ := requestToServer(url, app, chromeUA, acceptWebP)
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
}
@ -147,29 +153,26 @@ func TestConvertProxyModeWork(t *testing.T) {
config.ImgPath = "https://webp.sh"
url := "https://webp.sh/images/cover.jpg"
resp, data := requestToServer(url, app, chromeUA)
resp, data := requestToServer(url, app, chromeUA, acceptWebP)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "image/webp", getFileContentType(data))
// test proxyMode with Safari
resp, data = requestToServer(url, app, safariUA)
resp, data = requestToServer(url, app, safariUA, acceptLegacy)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "image/jpeg", getFileContentType(data))
}
func TestConvertBigger(t *testing.T) {
setupParam()
config.Quality = "100"
jpg, _ := ioutil.ReadFile("pics/big.jpg")
config.Quality = 100
var app = fiber.New()
app.Get("/*", convert)
url := "http://127.0.0.1:3333/big.jpg"
response, data := requestToServer(url, app, chromeUA)
response, data := requestToServer(url, app, chromeUA, acceptWebP)
assert.Equal(t, "image/jpeg", response.Header.Get("content-type"))
assert.True(t, len(data) == len(jpg))
assert.Equal(t, "image/jpeg", getFileContentType(data))
_ = os.RemoveAll(config.ExhaustPath)
}

View File

@ -23,7 +23,7 @@ func Test404AutoUpdate(t *testing.T) {
dir := "./update"
releaseUrl = releaseUrl + "a"
autoUpdate()
assert.Equal(t, 0, fileCount(dir))
assert.Equal(t, int64(0), fileCount(dir))
_ = os.RemoveAll(dir)
}

View File

@ -21,7 +21,7 @@ func TestLoadConfig(t *testing.T) {
assert.Equal(t, "./exhaust", c.ExhaustPath)
assert.Equal(t, "127.0.0.1", c.Host)
assert.Equal(t, "3333", c.Port)
assert.Equal(t, "80", c.Quality)
assert.Equal(t, float32(80), c.Quality)
assert.Equal(t, "./pics", c.ImgPath)
assert.Equal(t, []string{"jpg", "png", "jpeg", "bmp"}, c.AllowedTypes)
}
@ -43,7 +43,7 @@ func TestMainFunction(t *testing.T) {
// run main function
go main()
time.Sleep(time.Second * 2)
time.Sleep(time.Second * 5)
// verbose, prefetch
assert.Equal(t, log.GetLevel(), log.DebugLevel)
assert.True(t, verboseMode)