From 5e2052a71134f38258adf51533894e4835fe68a5 Mon Sep 17 00:00:00 2001 From: wood chen Date: Mon, 28 Oct 2024 16:56:29 +0800 Subject: [PATCH] refactor(api): migrate from Fiber to Gin framework Migrate the web framework from Fiber to Gin for better performance and community support. --- config/config.go | 10 +-- go.mod | 28 ++++++-- go.sum | 78 ++++++++++++++++++--- go.work.sum | 3 +- handler/healthz.go | 8 ++- handler/remote.go | 5 +- handler/router.go | 166 ++++++++++++++++++++++++++++++--------------- webp-server.go | 63 ++++++++++------- 8 files changed, 255 insertions(+), 106 deletions(-) diff --git a/config/config.go b/config/config.go index 64b9145..c80f596 100644 --- a/config/config.go +++ b/config/config.go @@ -17,11 +17,11 @@ import ( const ( TimeDateFormat = "2006-01-02 15:04:05" - FiberLogFormat = "${ip} - [${time}] ${method} ${url} ${status} ${referer} ${ua}\n" - WebpMax = 16383 - AvifMax = 65536 - HttpRegexp = `^https?://` - SampleConfig = ` + // GinLogFormat = "%s - [%s] \"%s %s %s\" %d %s \"%s\" %s" + WebpMax = 16383 + AvifMax = 65536 + HttpRegexp = `^https?://` + SampleConfig = ` { "HOST": "127.0.0.1", "PORT": "3333", diff --git a/go.mod b/go.mod index 87ea4cb..fe80d10 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23 require ( github.com/cespare/xxhash v1.1.0 github.com/davidbyttow/govips/v2 v2.15.0 - github.com/gofiber/fiber/v2 v2.52.5 + github.com/gin-gonic/gin v1.10.0 github.com/h2non/filetype v1.1.4-0.20230123234534-cfcd7d097bc4 github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c github.com/jeremytorres/rawparser v1.0.2 @@ -17,20 +17,38 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/google/uuid v1.6.0 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.9 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/jeremytorres/rawparser v1.0.2 => github.com/webp-sh/rawparser v0.0.0-20240311121240-15117cd3320a diff --git a/go.sum b/go.sum index a6cd29c..08abe24 100644 --- a/go.sum +++ b/go.sum @@ -2,42 +2,79 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidbyttow/govips/v2 v2.15.0 h1:h3lF+rQElBzGXbQSSPqmE3XGySPhcQo2x3t5l/dZ+pU= github.com/davidbyttow/govips/v2 v2.15.0/go.mod h1:3OQCHj0nf5Mnrplh5VlNvmx3IhJXyxbAoTJZPflUjmM= -github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= -github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/h2non/filetype v1.1.4-0.20230123234534-cfcd7d097bc4 h1:k7FGP5I7raiaC3aAzCLddcoxzboIrOm6/FVRXjp/5JM= github.com/h2non/filetype v1.1.4-0.20230123234534-cfcd7d097bc4/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/schollz/progressbar/v3 v3.16.1 h1:RnF1neWZFzLCoGx8yp1yF7SDl4AzNDI5y4I0aUJRrZQ= @@ -47,23 +84,37 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.56.0 h1:bEZdJev/6LCBlpdORfrLu/WOZXXxvrUQSiyniuaoW8U= github.com/valyala/fasthttp v1.56.0/go.mod h1:sReBt3XZVnudxuLOx4J/fMrJVorWRiWY2koQKgABiVI= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/webp-sh/rawparser v0.0.0-20240311121240-15117cd3320a h1:yFNUYbDL81wQZ7AQmBhkS+ZDfTugwepVI4LUQ/tQBAc= github.com/webp-sh/rawparser v0.0.0-20240311121240-15117cd3320a/go.mod h1:X0j2dOqH3ecGRuWvkThgDy+NKAfIwSN9wAOQlMcFOfY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= @@ -87,7 +138,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -117,8 +167,14 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/go.work.sum b/go.work.sum index ea60717..a8d895c 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,7 +1,8 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/handler/healthz.go b/handler/healthz.go index 30c0cde..9579b4d 100644 --- a/handler/healthz.go +++ b/handler/healthz.go @@ -1,9 +1,11 @@ package handler import ( - "github.com/gofiber/fiber/v2" + "net/http" + + "github.com/gin-gonic/gin" ) -func Healthz(c *fiber.Ctx) error { - return c.SendString("WebP Server Go up and running!🥳") +func Healthz(c *gin.Context) { + c.String(http.StatusOK, "WebP Server Go up and running!🥳") } diff --git a/handler/remote.go b/handler/remote.go index db8598b..e061578 100644 --- a/handler/remote.go +++ b/handler/remote.go @@ -12,7 +12,6 @@ import ( "webp_server_go/config" "webp_server_go/helper" - "github.com/gofiber/fiber/v2" log "github.com/sirupsen/logrus" ) @@ -39,7 +38,7 @@ func downloadFile(filepath string, url string) error { } defer resp.Body.Close() - if resp.StatusCode != fiber.StatusOK { + if resp.StatusCode != http.StatusOK { log.Errorf("获取远程图像失败。上游链接: %s, 状态码: %s", url, resp.Status) return fmt.Errorf("远程服务器返回非预期状态") } @@ -103,7 +102,7 @@ func pingURL(url string) (string, int64, time.Time) { } defer resp.Body.Close() - if resp.StatusCode == fiber.StatusOK { + if resp.StatusCode == http.StatusOK { etag = resp.Header.Get("ETag") sizeStr := resp.Header.Get("Content-Length") size, _ = strconv.ParseInt(sizeStr, 10, 64) diff --git a/handler/router.go b/handler/router.go index a320281..b85b8fb 100644 --- a/handler/router.go +++ b/handler/router.go @@ -8,42 +8,55 @@ import ( "slices" "strconv" "strings" + "sync" "webp_server_go/config" "webp_server_go/encoder" "webp_server_go/helper" "webp_server_go/schedule" - "github.com/gofiber/fiber/v2" + "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" ) -func Convert(c *fiber.Ctx) error { +// 文件锁映射 +var fileLocks = sync.Map{} + +// 获取文件锁 +func getFileLock(filename string) *sync.Mutex { + actual, _ := fileLocks.LoadOrStore(filename, &sync.Mutex{}) + return actual.(*sync.Mutex) +} + +func Convert(c *gin.Context) { // 检查是否为根路径 - if c.Path() == "/" { - return c.SendString("Welcome to CZL WebP Server") + if c.Request.URL.Path == "/" { + c.String(200, "Welcome to CZL WebP Server") + return } var ( - reqURIRaw, _ = url.QueryUnescape(c.Path()) - reqURIwithQueryRaw, _ = url.QueryUnescape(c.OriginalURL()) + reqURIRaw, _ = url.QueryUnescape(c.Request.URL.Path) + reqURIwithQueryRaw, _ = url.QueryUnescape(c.Request.URL.RequestURI()) reqURI = path.Clean(reqURIRaw) reqURIwithQuery = path.Clean(reqURIwithQueryRaw) filename = path.Base(reqURI) ) - log.Debugf("Incoming connection from %s %s", c.IP(), reqURIwithQuery) + log.Debugf("Incoming connection from %s %s", c.ClientIP(), reqURIwithQuery) // 首先检查是否为图片文件 if !isImageFile(filename) { log.Infof("Non-image file requested: %s", reqURI) - return handleNonImageFile(c, reqURI) + handleNonImageFile(c, reqURI) + return } // 检查文件类型是否允许 if !helper.CheckAllowedType(filename) { msg := "File extension not allowed! " + filename log.Warn(msg) - return c.Status(fiber.StatusBadRequest).SendString(msg) + c.String(400, msg) + return } // 解析额外参数 @@ -52,8 +65,9 @@ func Convert(c *fiber.Ctx) error { // 检查路径是否匹配 IMG_MAP 中的任何前缀 matchedPrefix, matchedTarget := findMatchingPrefix(reqURI) if matchedPrefix == "" { - log.Warnf("请求的路径不匹配任何配置的 IMG_MAP: %s", c.Path()) - return c.SendStatus(fiber.StatusNotFound) + log.Warnf("请求的路径不匹配任何配置的 IMG_MAP: %s", c.Request.URL.Path) + c.Status(404) + return } // 构建 EXHAUST_PATH 中的文件路径 @@ -61,20 +75,25 @@ func Convert(c *fiber.Ctx) error { // 检查文件是否已经在 EXHAUST_PATH 中 if helper.FileExists(exhaustFilename) { - log.Infof("文件已存在于 EXHAUST_PATH,直接提供服务: %s", exhaustFilename) - return c.SendFile(exhaustFilename) + if info, err := os.Stat(exhaustFilename); err == nil && info.Size() > 0 { + log.Infof("文件已存在于 EXHAUST_PATH,直接提供服务: %s", exhaustFilename) + c.File(exhaustFilename) + return + } + // 如果文件存在但大小为0,删除它并重新处理 + os.Remove(exhaustFilename) } // 处理图像 isLocalPath := strings.HasPrefix(matchedTarget, "./") || strings.HasPrefix(matchedTarget, "/") if isLocalPath { - return handleLocalImage(c, matchedTarget, reqURI, exhaustFilename, extraParams) + handleLocalImage(c, matchedTarget, reqURI, exhaustFilename, extraParams) } else { - return handleRemoteImage(c, matchedTarget, matchedPrefix, reqURIwithQuery, exhaustFilename, extraParams) + handleRemoteImage(c, matchedTarget, matchedPrefix, reqURIwithQuery, exhaustFilename, extraParams) } } -func handleNonImageFile(c *fiber.Ctx, reqURI string) error { +func handleNonImageFile(c *gin.Context, reqURI string) { var redirectURL string for prefix, target := range config.Config.ImageMap { @@ -82,7 +101,9 @@ func handleNonImageFile(c *fiber.Ctx, reqURI string) error { if strings.HasPrefix(target, "http://") || strings.HasPrefix(target, "https://") { redirectURL = target + strings.TrimPrefix(reqURI, prefix) } else { - return c.SendFile(path.Join(target, strings.TrimPrefix(reqURI, prefix))) + localPath := path.Join(target, strings.TrimPrefix(reqURI, prefix)) + c.File(localPath) + return } break } @@ -91,14 +112,16 @@ func handleNonImageFile(c *fiber.Ctx, reqURI string) error { if redirectURL == "" { localPath := path.Join(config.Config.ImgPath, reqURI) if helper.FileExists(localPath) { - return c.SendFile(localPath) + c.File(localPath) + return } else { - return c.SendStatus(fiber.StatusNotFound) + c.Status(404) + return } } log.Infof("Redirecting to: %s", redirectURL) - return c.Redirect(redirectURL, fiber.StatusFound) + c.Redirect(302, redirectURL) } func isImageFile(filename string) bool { @@ -116,13 +139,13 @@ func isImageFile(filename string) bool { return slices.Contains(allowedTypes, ext) } -func parseRequestURI(c *fiber.Ctx) (string, string) { - reqURIRaw, _ := url.QueryUnescape(c.Path()) - reqURIwithQueryRaw, _ := url.QueryUnescape(c.OriginalURL()) +func parseRequestURI(c *gin.Context) (string, string) { + reqURIRaw, _ := url.QueryUnescape(c.Request.URL.Path) + reqURIwithQueryRaw, _ := url.QueryUnescape(c.Request.URL.RequestURI()) return path.Clean(reqURIRaw), path.Clean(reqURIwithQueryRaw) } -func parseExtraParams(c *fiber.Ctx) config.ExtraParams { +func parseExtraParams(c *gin.Context) config.ExtraParams { width, _ := strconv.Atoi(c.Query("width")) height, _ := strconv.Atoi(c.Query("height")) maxHeight, _ := strconv.Atoi(c.Query("max_height")) @@ -144,6 +167,15 @@ func findMatchingPrefix(reqURI string) (string, string) { return "", "" } +func buildRealRemoteAddr(targetUrl *url.URL, matchedPrefix, reqURIwithQuery string) string { + targetHost := targetUrl.Scheme + "://" + targetUrl.Host + reqURIwithQuery = strings.Replace(reqURIwithQuery, matchedPrefix, targetUrl.Path, 1) + if strings.HasSuffix(targetUrl.Path, "/") { + reqURIwithQuery = strings.TrimPrefix(reqURIwithQuery, "/") + } + return targetHost + reqURIwithQuery +} + func buildExhaustFilename(reqURI string, extraParams config.ExtraParams) string { exhaustFilename := path.Join(config.Config.ExhaustPath, reqURI) if extraParams.Width > 0 || extraParams.Height > 0 || extraParams.MaxWidth > 0 || extraParams.MaxHeight > 0 { @@ -154,21 +186,28 @@ func buildExhaustFilename(reqURI string, extraParams config.ExtraParams) string return exhaustFilename } -func handleLocalImage(c *fiber.Ctx, matchedTarget, reqURI, exhaustFilename string, extraParams config.ExtraParams) error { +func handleLocalImage(c *gin.Context, matchedTarget, reqURI, exhaustFilename string, extraParams config.ExtraParams) { rawImageAbs := path.Join(matchedTarget, reqURI) if !helper.FileExists(rawImageAbs) { - return c.Status(fiber.StatusNotFound).SendString("本地文件不存在") + c.String(404, "本地文件不存在") + return } - return processAndSaveImage(c, rawImageAbs, exhaustFilename, extraParams) + err := processAndSaveImage(c, rawImageAbs, exhaustFilename, extraParams) + if err != nil { + log.Error(err) + c.String(500, "处理图像时出错") + return + } } -func handleRemoteImage(c *fiber.Ctx, matchedTarget, matchedPrefix, reqURIwithQuery, exhaustFilename string, extraParams config.ExtraParams) error { +func handleRemoteImage(c *gin.Context, matchedTarget, matchedPrefix, reqURIwithQuery, exhaustFilename string, extraParams config.ExtraParams) { targetUrl, err := url.Parse(matchedTarget) if err != nil { log.Errorf("解析目标 URL 失败: %v", err) - return c.Status(fiber.StatusInternalServerError).SendString("服务器配置错误") + c.String(500, "服务器配置错误") + return } realRemoteAddr := buildRealRemoteAddr(targetUrl, matchedPrefix, reqURIwithQuery) @@ -176,58 +215,75 @@ func handleRemoteImage(c *fiber.Ctx, matchedTarget, matchedPrefix, reqURIwithQue rawImageAbs, isNewDownload, err := fetchRemoteImg(realRemoteAddr, targetUrl.Host) if err != nil { log.Errorf("获取远程图像失败: %v", err) - return c.Status(fiber.StatusInternalServerError).SendString("无法获取远程图像") + c.String(500, "无法获取远程图像") + return } err = processAndSaveImage(c, rawImageAbs, exhaustFilename, extraParams) if err != nil { - return err + log.Error(err) + c.String(500, "处理图像时出错") + return } if isNewDownload { go schedule.ScheduleCleanup(rawImageAbs) } - - return c.SendFile(exhaustFilename) } -func buildRealRemoteAddr(targetUrl *url.URL, matchedPrefix, reqURIwithQuery string) string { - targetHost := targetUrl.Scheme + "://" + targetUrl.Host - reqURIwithQuery = strings.Replace(reqURIwithQuery, matchedPrefix, targetUrl.Path, 1) - if strings.HasSuffix(targetUrl.Path, "/") { - reqURIwithQuery = strings.TrimPrefix(reqURIwithQuery, "/") +func processAndSaveImage(c *gin.Context, rawImageAbs, exhaustFilename string, extraParams config.ExtraParams) error { + // 获取文件锁 + lock := getFileLock(exhaustFilename) + lock.Lock() + defer lock.Unlock() + + // 再次检查文件是否存在 + if helper.FileExists(exhaustFilename) { + if info, err := os.Stat(exhaustFilename); err == nil && info.Size() > 0 { + c.File(exhaustFilename) + return nil + } + os.Remove(exhaustFilename) } - return targetHost + reqURIwithQuery -} -func processAndSaveImage(c *fiber.Ctx, rawImageAbs, exhaustFilename string, extraParams config.ExtraParams) error { - isSmall, err := helper.IsFileSizeSmall(rawImageAbs, 30*1024) // 30KB + isSmall, err := helper.IsFileSizeSmall(rawImageAbs, 30*1024) if err != nil { - log.Errorf("检查文件大小时出错: %v", err) - return c.Status(fiber.StatusInternalServerError).SendString("处理图像时出错") + return fmt.Errorf("检查文件大小时出错: %v", err) } + // 确保目标目录存在 if err := os.MkdirAll(path.Dir(exhaustFilename), 0755); err != nil { - log.Errorf("创建目标目录失败: %v", err) - return c.Status(fiber.StatusInternalServerError).SendString("服务器错误") + return fmt.Errorf("创建目标目录失败: %v", err) } + // 使用临时文件 + tempFile := exhaustFilename + ".tmp" + defer os.Remove(tempFile) + if isSmall { - if err := helper.CopyFile(rawImageAbs, exhaustFilename); err != nil { - log.Errorf("复制小文件到 EXHAUST_PATH 失败: %v", err) - return c.Status(fiber.StatusInternalServerError).SendString("处理图像时出错") + if err := helper.CopyFile(rawImageAbs, tempFile); err != nil { + return fmt.Errorf("复制小文件失败: %v", err) } } else { - err := encoder.ProcessAndSaveImage(rawImageAbs, exhaustFilename, extraParams) + err := encoder.ProcessAndSaveImage(rawImageAbs, tempFile, extraParams) if err != nil { log.Warnf("处理图片失败,将直接复制原图: %v", err) - if copyErr := helper.CopyFile(rawImageAbs, exhaustFilename); copyErr != nil { - log.Errorf("复制原图到 EXHAUST_PATH 失败: %v", copyErr) - return c.Status(fiber.StatusInternalServerError).SendString("处理图像时出错") + if copyErr := helper.CopyFile(rawImageAbs, tempFile); copyErr != nil { + return fmt.Errorf("复制原图失败: %v", copyErr) } - log.Infof("已将原图复制到 EXHAUST_PATH: %s", exhaustFilename) } } - return c.SendFile(exhaustFilename) + // 验证临时文件 + if info, err := os.Stat(tempFile); err != nil || info.Size() == 0 { + return fmt.Errorf("处理后的文件无效") + } + + // 原子性地将临时文件重命名为目标文件 + if err := os.Rename(tempFile, exhaustFilename); err != nil { + return fmt.Errorf("重命名临时文件失败: %v", err) + } + + c.File(exhaustFilename) + return nil } diff --git a/webp-server.go b/webp-server.go index 3209347..557745b 100644 --- a/webp-server.go +++ b/webp-server.go @@ -3,32 +3,20 @@ package main import ( "flag" "fmt" + "net/http" "os" "runtime" "time" "webp_server_go/config" "webp_server_go/encoder" "webp_server_go/handler" - schedule "webp_server_go/schedule" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/logger" - "github.com/gofiber/fiber/v2/middleware/recover" + "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" ) -// https://docs.gofiber.io/api/fiber -var app = fiber.New(fiber.Config{ - ServerHeader: "WebP Server Go", - AppName: "WebP Server Go", - DisableStartupMessage: true, - ProxyHeader: "X-Real-IP", - ReadBufferSize: config.Config.ReadBufferSize, // 用于请求读取的每个连接缓冲区大小。这也限制了最大标头大小。如果您的客户端发送多 KB RequestURI 和/或多 KB 标头(例如,BIG cookies),请增加此缓冲区。 - WriteBufferSize: 1024 * 4, - Concurrency: config.Config.Concurrency, // 最大并发连接数。 - DisableKeepalive: config.Config.DisableKeepalive, // 禁用保持活动连接,服务器将在向客户端发送第一个响应后关闭传入连接 -}) +var router *gin.Engine func setupLogger() { log.SetOutput(os.Stdout) @@ -44,12 +32,23 @@ func setupLogger() { log.SetFormatter(formatter) log.SetLevel(log.InfoLevel) - // fiber logger format - app.Use(logger.New(logger.Config{ - Format: config.FiberLogFormat, - TimeFormat: config.TimeDateFormat, + // 设置 Gin 的日志格式 + gin.SetMode(gin.ReleaseMode) + router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { + return fmt.Sprintf("%s - [%s] \"%s %s %s\" %d %s \"%s\" %s\n", + param.ClientIP, + param.TimeStamp.Format(config.TimeDateFormat), + param.Method, + param.Path, + param.Request.Proto, + param.StatusCode, + param.Latency, + param.Request.UserAgent(), + param.ErrorMessage, + ) })) - app.Use(recover.New(recover.Config{})) + router.Use(gin.Recovery()) + fmt.Println("Allowed file types as source:", config.Config.AllowedTypes) fmt.Println("Convert to WebP Enabled:", config.Config.EnableWebP) fmt.Println("Convert to AVIF Enabled:", config.Config.EnableAVIF) @@ -66,6 +65,7 @@ func init() { WebP Server Go - v%s Developed by WebP Server team. https://github.com/webp-sh`, config.Version) + // main init is the last one to be called flag.Parse() // process cli params @@ -79,6 +79,9 @@ func init() { } config.LoadConfig() fmt.Printf("\n %c[1;32m%s%c[0m\n\n", 0x1B, banner, 0x1B) + + // 初始化 Gin 路由 + router = gin.New() setupLogger() } @@ -106,12 +109,26 @@ func main() { listenAddress := config.Config.Host + ":" + config.Config.Port - app.Get("/healthz", handler.Healthz) - app.Get("/*", handler.Convert) + // 设置路由 + router.GET("/healthz", handler.Healthz) + router.Any("/*path", handler.Convert) // 使用 Any 来匹配所有方法 + + // 设置服务器参数 + server := &http.Server{ + Addr: listenAddress, + Handler: router, + ReadTimeout: time.Second * 30, + WriteTimeout: time.Second * 30, + ReadHeaderTimeout: time.Second * 10, + MaxHeaderBytes: config.Config.ReadBufferSize, + } go monitorMemoryUsage() fmt.Println("WebP Server Go is Running on http://" + listenAddress) - _ = app.Listen(listenAddress) + // 启动服务器 + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("Failed to start server: %v", err) + } }