mirror of
https://github.com/woodchen-ink/webp_server_go.git
synced 2025-07-18 13:42:02 +08:00
iOS 14 support, bump to 0.3.1 (#63)
Use `accept` header first, then `user-agent` header. Add complete test case. This should resolve part of #61
This commit is contained in:
parent
9136beb307
commit
37d8d8ba13
@ -14,7 +14,8 @@ It will convert `jpg,jpeg,png` files by default, this can be customized by editi
|
|||||||
|
|
||||||
> e.g When you visit `https://your.website/pics/tsuki.jpg`,it will serve as `image/webp` format without changing the URL.
|
> e.g When you visit `https://your.website/pics/tsuki.jpg`,it will serve as `image/webp` format without changing the URL.
|
||||||
>
|
>
|
||||||
> For Safari and Opera users, the original image will be used.
|
> ~~For Safari and Opera users, the original image will be used.~~
|
||||||
|
> We've now support Safari/Chrome/Firefox on iOS 14/iPadOS 14
|
||||||
|
|
||||||
|
|
||||||
## Simple Usage Steps
|
## Simple Usage Steps
|
||||||
|
@ -21,7 +21,7 @@ var (
|
|||||||
prefetch, proxyMode bool
|
prefetch, proxyMode bool
|
||||||
|
|
||||||
config Config
|
config Config
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
32
helper.go
32
helper.go
@ -143,13 +143,26 @@ func getCompressionRate(RawImagePath string, webpAbsPath string) string {
|
|||||||
return fmt.Sprintf(`%.2f`, compressionRate)
|
return fmt.Sprintf(`%.2f`, compressionRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func goOrigin(UA string) bool {
|
func goOrigin(header, ua string) bool {
|
||||||
|
// We'll first check accept headers, if accept headers is false, we'll then go to UA part
|
||||||
|
if headerOrigin(header) && uaOrigin(ua) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func uaOrigin(ua string) bool {
|
||||||
|
// iOS 14 and iPadOS 14 supports webp, the identification token is iPhone OS 14_2_1 and CPU OS 14_2
|
||||||
// for more information, please check test case
|
// for more information, please check test case
|
||||||
if strings.Contains(UA, "Firefox") || strings.Contains(UA, "Chrome") {
|
if strings.Contains(ua, "iPhone OS 14") || strings.Contains(ua, "CPU OS 14") {
|
||||||
|
// this is iOS 14/iPadOS 14
|
||||||
|
return false
|
||||||
|
} else if strings.Contains(ua, "Firefox") || strings.Contains(ua, "Chrome") {
|
||||||
// Chrome or firefox on macOS Windows
|
// Chrome or firefox on macOS Windows
|
||||||
} else if strings.Contains(UA, "Android") || strings.Contains(UA, "Linux") {
|
} else if strings.Contains(ua, "Android") || strings.Contains(ua, "Linux") {
|
||||||
// on Android and Linux
|
// on Android and Linux
|
||||||
} else if strings.Contains(UA, "FxiOS") || strings.Contains(UA, "CriOS") {
|
} else if strings.Contains(ua, "FxiOS") || strings.Contains(ua, "CriOS") {
|
||||||
//firefox and Chrome on iOS
|
//firefox and Chrome on iOS
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
@ -157,3 +170,14 @@ func goOrigin(UA string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func headerOrigin(header string) bool {
|
||||||
|
// Webkit is really weird especially on iOS, it doesn't even send out effective accept headers.
|
||||||
|
// Head to test case if you want to know more
|
||||||
|
if strings.Contains(header, "image/webp") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// go to origin
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -64,9 +64,38 @@ func TestGenEtag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGoOrigin(t *testing.T) {
|
func TestGoOrigin(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{
|
||||||
|
// 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
for value, is := range testCase {
|
||||||
|
assert.Equalf(t, is, goOrigin(value[0], value[1]), "[%v]:[%s]", value, is)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUaOrigin(t *testing.T) {
|
||||||
// reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
|
// 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
|
// https://developer.chrome.com/multidevice/user-agent#chrome_for_ios_user_agent
|
||||||
|
|
||||||
|
// UNLESS YOU KNOW WHAT YOU ARE DOING, DO NOT CHANGE THE TEST CASE MAPPING HERE.
|
||||||
var testCase = map[string]bool{
|
var testCase = map[string]bool{
|
||||||
// Chrome on Windows, macOS, linux, iOS and Android
|
// 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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36": false,
|
||||||
@ -98,14 +127,37 @@ func TestGoOrigin(t *testing.T) {
|
|||||||
// Others
|
// Others
|
||||||
"PostmanRuntime/7.26.1": true,
|
"PostmanRuntime/7.26.1": true,
|
||||||
"curl/7.64.1": true,
|
"curl/7.64.1": true,
|
||||||
|
|
||||||
|
// 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
for browser, is := range testCase {
|
for browser, is := range testCase {
|
||||||
assert.Equalf(t, is, goOrigin(browser), "[%v]:[%s]", is, browser)
|
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) {
|
func TestChanErr(t *testing.T) {
|
||||||
var value = 2
|
var value = 2
|
||||||
var testC = make(chan int, 2)
|
var testC = make(chan int, 2)
|
||||||
|
@ -19,12 +19,13 @@ func convert(c *fiber.Ctx) error {
|
|||||||
var rawImageAbs = path.Join(config.ImgPath, reqURI) // /home/xxx/mypic/123.jpg
|
var rawImageAbs = path.Join(config.ImgPath, reqURI) // /home/xxx/mypic/123.jpg
|
||||||
var imgFilename = path.Base(reqURI) // pure filename, 123.jpg
|
var imgFilename = path.Base(reqURI) // pure filename, 123.jpg
|
||||||
var finalFile string // We'll only need one c.sendFile()
|
var finalFile string // We'll only need one c.sendFile()
|
||||||
var UA = c.Get("User-Agent")
|
var ua = c.Get("User-Agent")
|
||||||
log.Debugf("Incoming connection from %s@%s with %s", UA, c.IP(), imgFilename)
|
var accept = c.Get("accept")
|
||||||
|
log.Debugf("Incoming connection from %s@%s with %s", ua, c.IP(), imgFilename)
|
||||||
|
|
||||||
needOrigin := goOrigin(UA)
|
needOrigin := goOrigin(accept, ua)
|
||||||
if needOrigin {
|
if needOrigin {
|
||||||
log.Infof("A Safari/IE/whatever user has arrived...%s", UA)
|
log.Infof("A Safari/IE/whatever user has arrived...%s", ua)
|
||||||
// Check for Safari users. If they're Safari, just simply ignore everything.
|
// Check for Safari users. If they're Safari, just simply ignore everything.
|
||||||
etag := genEtag(rawImageAbs)
|
etag := genEtag(rawImageAbs)
|
||||||
c.Set("ETag", etag)
|
c.Set("ETag", etag)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Name: webp-server
|
Name: webp-server
|
||||||
Version: 0.3.0
|
Version: 0.3.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.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user