Merge branch 'master' into old-engine

This commit is contained in:
nikk gitanes
2023-03-02 05:02:55 +03:00
93 changed files with 170 additions and 119 deletions

51
server/ffprobe/ffprobe.go Normal file
View File

@@ -0,0 +1,51 @@
package ffprobe
import (
"context"
"gopkg.in/vansante/go-ffprobe.v2"
"io"
"os"
"os/exec"
"path/filepath"
"time"
)
var binFile = "ffprobe"
func init() {
path, err := exec.LookPath("ffprobe")
if err == nil {
ffprobe.SetFFProbeBinPath(path)
binFile = path
} else {
// working dir
if _, err := os.Stat("ffprobe"); os.IsNotExist(err) {
ffprobe.SetFFProbeBinPath(filepath.Dir(os.Args[0]) + "/ffprobe")
binFile = filepath.Dir(os.Args[0]) + "/ffprobe"
}
}
}
func Exists() bool {
_, err := os.Stat(binFile)
return !os.IsNotExist(err)
}
func ProbeUrl(link string) (*ffprobe.ProbeData, error) {
data, err := ffprobe.ProbeURL(getCtx(), link)
return data, err
}
func ProbeReader(reader io.Reader) (*ffprobe.ProbeData, error) {
data, err := ffprobe.ProbeReader(getCtx(), reader)
return data, err
}
func getCtx() context.Context {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(5 * time.Minute)
cancel()
}()
return ctx
}

View File

@@ -11,7 +11,7 @@ require (
github.com/anacrolix/log v0.13.2-0.20221123232138-02e2764801c3
github.com/anacrolix/missinggo v1.3.0
github.com/anacrolix/publicip v0.3.0
github.com/anacrolix/torrent v1.48.1-0.20230214014649-2cb7121a93c7
github.com/anacrolix/torrent v1.48.1-0.20230301031729-c069849b4040
github.com/gin-contrib/cors v1.4.0
github.com/gin-contrib/location v0.0.2
github.com/gin-gonic/gin v1.8.1

View File

@@ -71,6 +71,8 @@ github.com/anacrolix/sync v0.4.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DC
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8=
github.com/anacrolix/torrent v1.48.1-0.20230301031729-c069849b4040 h1:QJUcCAfKObrE/XVTDSzer0uhCR3iCSzFY135LInL5Bg=
github.com/anacrolix/torrent v1.48.1-0.20230301031729-c069849b4040/go.mod h1:qT3yS5oQwDUHnBXy+zf3nozLPudG7SFNDL3Jl/zQwFw=
github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96 h1:QAVZ3pN/J4/UziniAhJR2OZ9Ox5kOY2053tBbbqUPYA=
github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96/go.mod h1:Wa6n8cYIdaG35x15aH3Zy6d03f7P728QfdcDeD/IEOs=
github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4=

View File

@@ -7,7 +7,6 @@ import (
"log"
"os"
"strings"
"time"
"github.com/gin-gonic/gin"
)
@@ -52,15 +51,16 @@ func Init(path, webpath string) {
logFile = ff
os.Stdout = ff
os.Stderr = ff
var timeFmt string
var ok bool
timeFmt, ok = os.LookupEnv("GO_LOG_TIME_FMT")
if !ok {
timeFmt = "2006-01-02T15:04:05-0700"
}
t := time.Now().Format(timeFmt)
log.SetFlags(log.Lmsgprefix)
log.SetPrefix(t + " TSM ")
// var timeFmt string
// var ok bool
// timeFmt, ok = os.LookupEnv("GO_LOG_TIME_FMT")
// if !ok {
// timeFmt = "2006-01-02T15:04:05-0700"
// }
// log.SetFlags(log.Lmsgprefix)
// log.SetPrefix(time.Now().Format(timeFmt) + " TSM ")
log.SetFlags(log.LstdFlags | log.LUTC | log.Lmsgprefix)
log.SetPrefix("UTC0 ")
log.SetOutput(ff)
}
}

View File

@@ -42,6 +42,7 @@ func init() {
{"video/mp2t", ".ts,.m2ts,.mts"},
{"video/ogg", ".ogv"},
{"video/webm", ".webm"},
{"video/x-ms-vob", ".vob"},
{"video/x-msvideo", ".avi"},
{"video/x-quicktime", ".qt,.mov"},
{"text/srt", ".srt"},

View File

@@ -58,6 +58,16 @@ func Stop() {
// http://releases.yourok.ru/torr/rutor.ls
func updateDB() bool {
log.TLogln("Update rutor db")
fnOrig := filepath.Join(settings.Path, "rutor.ls")
if fi, err := os.Stat(fnOrig); err == nil {
if time.Since(fi.ModTime()) < time.Minute*175 /*2:55*/ {
log.TLogln("Less 3 hours rutor db old")
return false
}
}
fnTmp := filepath.Join(settings.Path, "rutor.tmp")
out, err := os.Create(fnTmp)
if err != nil {
@@ -79,8 +89,6 @@ func updateDB() bool {
return false
}
fnOrig := filepath.Join(settings.Path, "rutor.ls")
md5Tmp := utils.MD5File(fnTmp)
md5Orig := utils.MD5File(fnOrig)
if md5Tmp != md5Orig {

View File

@@ -3,6 +3,8 @@ package torr
import (
"fmt"
"io"
"server/ffprobe"
"strconv"
"sync"
"time"
@@ -63,8 +65,16 @@ func (t *Torrent) Preload(index int, size int64) {
}
}()
if ffprobe.Exists() {
host := "http://127.0.0.1:" + settings.Port + "/play/" + t.Hash().HexString() + "/" + strconv.Itoa(index) // + "&play"
if data, err := ffprobe.ProbeUrl(host); err == nil {
t.BitRate = data.Format.BitRate
t.DurationSeconds = data.Format.DurationSeconds
}
}
// startend -> 8/16 MB
startend := int64(t.Info().PieceLength)
startend := t.Info().PieceLength
if startend < 8*1024*1024 {
startend = 8 * 1024 * 1024
}

View File

@@ -61,6 +61,8 @@ type TorrentStatus struct {
ChunksReadWasted int64 `json:"chunks_read_wasted,omitempty"`
PiecesDirtiedGood int64 `json:"pieces_dirtied_good,omitempty"`
PiecesDirtiedBad int64 `json:"pieces_dirtied_bad,omitempty"`
DurationSeconds float64 `json:"duration_seconds,omitempty"`
BitRate string `json:"bit_rate,omitempty"`
FileStats []*TorrentFileStat `json:"file_stats,omitempty"`
}

View File

@@ -42,6 +42,9 @@ type Torrent struct {
PreloadSize int64
PreloadedBytes int64
DurationSeconds float64
BitRate string
expiredTime time.Time
closed <-chan struct{}
@@ -116,9 +119,15 @@ func (t *Torrent) WaitInfo() bool {
}
func (t *Torrent) GotInfo() bool {
// log.TLogln("GotInfo state:", t.Stat)
if t.Stat == state.TorrentClosed {
return false
}
// assume we have info in preload state
// and dont override with TorrentWorking
if t.Stat == state.TorrentPreload {
return true
}
t.Stat = state.TorrentGettingInfo
if t.WaitInfo() {
t.Stat = state.TorrentWorking
@@ -247,11 +256,11 @@ func (t *Torrent) GetCache() *torrstor.Cache {
func (t *Torrent) drop() {
t.muTorrent.Lock()
defer t.muTorrent.Unlock()
if t.Torrent != nil {
t.Torrent.Drop()
t.Torrent = nil
}
t.muTorrent.Unlock()
}
func (t *Torrent) Close() {
@@ -277,6 +286,8 @@ func (t *Torrent) Status() *state.TorrentStatus {
st.Data = t.Data
st.Timestamp = t.Timestamp
st.TorrentSize = t.Size
st.BitRate = t.BitRate
st.DurationSeconds = t.DurationSeconds
if t.TorrentSpec != nil {
st.Hash = t.TorrentSpec.InfoHash.HexString()

View File

@@ -2,6 +2,7 @@ package utils
import (
"path/filepath"
"strings"
"server/torr/state"
)
@@ -16,7 +17,6 @@ var extVideo = map[string]interface{}{
".drc": nil,
".flv": nil,
".m2ts": nil,
".ts": nil,
".m2v": nil,
".m4p": nil,
".m4v": nil,
@@ -29,6 +29,7 @@ var extVideo = map[string]interface{}{
".mpeg": nil,
".mpg": nil,
".mpv": nil,
".mts": nil,
".mxf": nil,
".nsv": nil,
".ogg": nil,
@@ -38,6 +39,7 @@ var extVideo = map[string]interface{}{
".rmvb": nil,
".roq": nil,
".svi": nil,
".ts": nil,
".vob": nil,
".webm": nil,
".wmv": nil,
@@ -49,6 +51,9 @@ var extAudio = map[string]interface{}{
".aiff": nil,
".ape": nil,
".au": nil,
".dff": nil,
".dsd": nil,
".dsf": nil,
".flac": nil,
".gsm": nil,
".it": nil,
@@ -58,17 +63,22 @@ var extAudio = map[string]interface{}{
".mod": nil,
".mp3": nil,
".mpa": nil,
".mpga": nil,
".oga": nil,
".ogg": nil,
".opus": nil,
".pls": nil,
".ra": nil,
".s3m": nil,
".sid": nil,
".spx": nil,
".wav": nil,
".wma": nil,
".xm": nil,
}
func GetMimeType(filename string) string {
ext := filepath.Ext(filename)
ext := strings.ToLower(filepath.Ext(filename))
if _, ok := extVideo[ext]; ok {
return "video/*"
}

View File

@@ -1,25 +1,15 @@
package api
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"server/utils"
"server/ffprobe"
settings2 "server/settings"
"github.com/gin-gonic/gin"
"gopkg.in/vansante/go-ffprobe.v2"
)
func commandExists(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
}
func ffp(c *gin.Context) {
hash := c.Param("hash")
indexStr := c.Param("id")
@@ -29,26 +19,9 @@ func ffp(c *gin.Context) {
return
}
host := utils.GetScheme(c) + "://" + c.Request.Host + "/stream?link=" + hash + "&index=" + indexStr + "&play"
// log.Println("ffprobe", host)
host := "http://127.0.0.1:" + settings2.Port + "/stream?link=" + hash + "&index=" + indexStr + "&play"
ctx, cancelFn := context.WithCancel(context.Background())
defer cancelFn()
// path lookup
path, err := exec.LookPath("ffprobe")
if err == nil {
// log.Println("ffprobe found in", path)
ffprobe.SetFFProbeBinPath(path)
} else {
// log.Println("ffprobe not found in $PATH")
// working dir
if _, err := os.Stat("ffprobe"); os.IsNotExist(err) {
ffprobe.SetFFProbeBinPath(filepath.Dir(os.Args[0]) + "/ffprobe")
}
}
data, err := ffprobe.ProbeURL(ctx, host)
data, err := ffprobe.ProbeUrl(host)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("error getting data: %v", err))
return

View File

@@ -62,8 +62,9 @@ func BasicAuth(accounts gin.Accounts) gin.HandlerFunc {
pairs := processAccounts(accounts)
return func(c *gin.Context) {
user, found := pairs.searchCredential(c.Request.Header.Get("Authorization"))
if !found {
if !found { // always accessible
if strings.HasPrefix(c.FullPath(), "/stream") ||
c.FullPath() == "/site.webmanifest" ||
// https://github.com/YouROK/TorrServer/issues/172
(strings.HasPrefix(c.FullPath(), "/play") && c.FullPath() != "/playlistall/all.m3u") {
c.Set("not_auth", true)

View File

@@ -28,8 +28,7 @@ func getTorrents(c *gin.Context) {
mi := metainfo.MetaInfo{
AnnounceList: ts.Trackers,
}
mag := mi.Magnet(ts.DisplayName, ts.InfoHash)
// mag := mi.Magnet(&ts.InfoHash, &metainfo.Info{Name: ts.DisplayName})
mag := mi.Magnet(&ts.InfoHash, &metainfo.Info{Name: ts.DisplayName})
http += "<p><a href='" + mag.String() + "'>magnet:?xt=urn:btih:" + mag.InfoHash.HexString() + "</a></p>"
}
http += "</div>"

View File

@@ -82,9 +82,6 @@ var Applesplash7501334jpg []byte
//go:embed pages/apple-splash-828-1792.jpg
var Applesplash8281792jpg []byte
//go:embed pages/apple-touch-icon.png
var Appletouchiconpng []byte
//go:embed pages/asset-manifest.json
var Assetmanifestjson []byte
@@ -103,17 +100,20 @@ var Favicon16x16png []byte
//go:embed pages/favicon-32x32.png
var Favicon32x32png []byte
//go:embed pages/favicon.ico
var Faviconico []byte
//go:embed pages/icon.png
var Iconpng []byte
//go:embed pages/index.html
var Indexhtml []byte
//go:embed pages/logo.png
var Logopng []byte
//go:embed pages/manifest-icon-192.maskable.png
var Manifesticon192maskablepng []byte
//go:embed pages/manifest-icon-512.maskable.png
var Manifesticon512maskablepng []byte
//go:embed pages/mstile-150x150.png
var Mstile150x150png []byte
//go:embed pages/site.webmanifest
var Sitewebmanifest []byte
@@ -127,11 +127,11 @@ var Staticjs2d3f8d41dchunkjsLICENSEtxt []byte
//go:embed pages/static/js/2.d3f8d41d.chunk.js.map
var Staticjs2d3f8d41dchunkjsmap []byte
//go:embed pages/static/js/main.4bd54915.chunk.js
var Staticjsmain4bd54915chunkjs []byte
//go:embed pages/static/js/main.e240e160.chunk.js
var Staticjsmaine240e160chunkjs []byte
//go:embed pages/static/js/main.4bd54915.chunk.js.map
var Staticjsmain4bd54915chunkjsmap []byte
//go:embed pages/static/js/main.e240e160.chunk.js.map
var Staticjsmaine240e160chunkjsmap []byte
//go:embed pages/static/js/runtime-main.64d07802.js
var Staticjsruntimemain64d07802js []byte

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 KiB

After

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 KiB

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 KiB

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 KiB

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 KiB

After

Width:  |  Height:  |  Size: 476 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 KiB

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 KiB

After

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 KiB

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 KiB

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

After

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

After

Width:  |  Height:  |  Size: 734 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 KiB

After

Width:  |  Height:  |  Size: 595 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

After

Width:  |  Height:  |  Size: 537 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 KiB

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 711 KiB

After

Width:  |  Height:  |  Size: 675 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 KiB

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

After

Width:  |  Height:  |  Size: 638 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 KiB

After

Width:  |  Height:  |  Size: 691 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 902 KiB

After

Width:  |  Height:  |  Size: 848 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 KiB

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View File

@@ -1,7 +1,7 @@
{
"files": {
"main.js": "/static/js/main.4bd54915.chunk.js",
"main.js.map": "/static/js/main.4bd54915.chunk.js.map",
"main.js": "/static/js/main.e240e160.chunk.js",
"main.js.map": "/static/js/main.e240e160.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.64d07802.js",
"runtime-main.js.map": "/static/js/runtime-main.64d07802.js.map",
"static/js/2.d3f8d41d.chunk.js": "/static/js/2.d3f8d41d.chunk.js",
@@ -12,6 +12,6 @@
"entrypoints": [
"static/js/runtime-main.64d07802.js",
"static/js/2.d3f8d41d.chunk.js",
"static/js/main.4bd54915.chunk.js"
"static/js/main.e240e160.chunk.js"
]
}

View File

@@ -3,7 +3,8 @@
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#00a300</TileColor>
<TileColor>#00a572</TileColor>
<TileImage src="/mstile-150x150.png" />
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -3,28 +3,16 @@
"short_name": "TorrServer",
"icons": [
{
"src": "manifest-icon-192.maskable.png",
"src": "icon.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "manifest-icon-192.maskable.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "manifest-icon-512.maskable.png",
"src": "logo.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "manifest-icon-512.maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -113,10 +113,6 @@ func RouteWebPages(route *gin.RouterGroup) {
c.Data(200, "image/jpeg", Applesplash8281792jpg)
})
route.GET("/apple-touch-icon.png", func(c *gin.Context) {
c.Data(200, "image/png", Appletouchiconpng)
})
route.GET("/asset-manifest.json", func(c *gin.Context) {
c.Data(200, "application/json", Assetmanifestjson)
})
@@ -141,6 +137,14 @@ func RouteWebPages(route *gin.RouterGroup) {
c.Data(200, "image/png", Favicon32x32png)
})
route.GET("/favicon.ico", func(c *gin.Context) {
c.Data(200, "image/vnd.microsoft.icon", Faviconico)
})
route.GET("/icon.png", func(c *gin.Context) {
c.Data(200, "image/png", Iconpng)
})
route.GET("/index.html", func(c *gin.Context) {
c.Data(200, "text/html; charset=utf-8", Indexhtml)
})
@@ -149,12 +153,8 @@ func RouteWebPages(route *gin.RouterGroup) {
c.Data(200, "image/png", Logopng)
})
route.GET("/manifest-icon-192.maskable.png", func(c *gin.Context) {
c.Data(200, "image/png", Manifesticon192maskablepng)
})
route.GET("/manifest-icon-512.maskable.png", func(c *gin.Context) {
c.Data(200, "image/png", Manifesticon512maskablepng)
route.GET("/mstile-150x150.png", func(c *gin.Context) {
c.Data(200, "image/png", Mstile150x150png)
})
route.GET("/site.webmanifest", func(c *gin.Context) {
@@ -173,12 +173,12 @@ func RouteWebPages(route *gin.RouterGroup) {
c.Data(200, "application/json", Staticjs2d3f8d41dchunkjsmap)
})
route.GET("/static/js/main.4bd54915.chunk.js", func(c *gin.Context) {
c.Data(200, "application/javascript; charset=utf-8", Staticjsmain4bd54915chunkjs)
route.GET("/static/js/main.e240e160.chunk.js", func(c *gin.Context) {
c.Data(200, "application/javascript; charset=utf-8", Staticjsmaine240e160chunkjs)
})
route.GET("/static/js/main.4bd54915.chunk.js.map", func(c *gin.Context) {
c.Data(200, "application/json", Staticjsmain4bd54915chunkjsmap)
route.GET("/static/js/main.e240e160.chunk.js.map", func(c *gin.Context) {
c.Data(200, "application/json", Staticjsmaine240e160chunkjsmap)
})
route.GET("/static/js/runtime-main.64d07802.js", func(c *gin.Context) {

View File

@@ -48,12 +48,13 @@ func Start(port string) {
// corsCfg.AllowHeaders = []string{"*"}
// corsCfg.AllowMethods = []string{"*"}
// corsCfg.AllowPrivateNetwork = true
corsCfg := cors.DefaultConfig()
corsCfg.AllowAllOrigins = true
corsCfg.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "X-Requested-With", "Accept", "Authorization"}
// corsCfg := cors.DefaultConfig()
// corsCfg.AllowAllOrigins = true
// corsCfg.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "X-Requested-With", "Accept", "Authorization"}
route := gin.New()
route.Use(log.WebLogger(), blocker.Blocker(), gin.Recovery(), cors.New(corsCfg), location.Default())
// cors.Default() allows all origins - https://github.com/gin-contrib/cors#default-allows-all-origins
route.Use(log.WebLogger(), blocker.Blocker(), gin.Recovery(), cors.Default(), location.Default())
route.GET("/echo", echo)