From f8f2d2cbfb86c54fc18e7a995e2cec8719507bd4 Mon Sep 17 00:00:00 2001 From: Kleissner Date: Sat, 24 Sep 2022 16:56:20 +0200 Subject: [PATCH] Include initial web router --- API.go | 7 ++++ Gateway.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++ Main.go | 8 ++++- README.md | 14 ++++++++ go.mod | 15 +++++---- go.sum | 22 +++++++------ html/favicon.ico | Bin 0 -> 7406 bytes html/index.html | 12 +++++++ 8 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 API.go create mode 100644 Gateway.go create mode 100644 html/favicon.ico create mode 100644 html/index.html diff --git a/API.go b/API.go new file mode 100644 index 0000000..d0f5b7e --- /dev/null +++ b/API.go @@ -0,0 +1,7 @@ +/* +File Name: API.go +Copyright: 2022 Peernet s.r.o. +Author: Peter Kleissner +*/ + +package main diff --git a/Gateway.go b/Gateway.go new file mode 100644 index 0000000..0685514 --- /dev/null +++ b/Gateway.go @@ -0,0 +1,82 @@ +/* +File Name: Gateway.go +Copyright: 2022 Peernet s.r.o. +Author: Peter Kleissner +*/ + +package main + +import ( + "crypto/tls" + "net" + "net/http" + "time" + + "github.com/PeernetOfficial/core" + "github.com/gorilla/mux" +) + +func startWebGateway(backend *core.Backend) { + router := mux.NewRouter() + router.PathPrefix("/").Handler(http.HandlerFunc(webGatewayHandler)).Methods("GET") + router.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir(config.WebFiles)))).Methods("GET") + + for _, listen := range config.WebListen { + go startWebServer(backend, listen, config.WebUseSSL, config.WebCertificateFile, config.WebCertificateKey, router, "Web Listen", parseDuration(config.WebTimeoutRead), parseDuration(config.WebTimeoutWrite)) + } + + if config.Redirect80 != "" { + go webRedirect80(config.Redirect80) + } + + // wait forever + select {} +} + +// startWebServer starts the web-server and may block forever +func startWebServer(backend *core.Backend, WebListen string, UseSSL bool, CertificateFile, CertificateKey string, Handler http.Handler, Info string, ReadTimeout, WriteTimeout time.Duration) { + //func startWebServer(backend *core.Backend, webListen string, useSSL bool, certificateFile, certificateKey string, server *http.Server) { + backend.LogError("startWebServer", "Web Gateway to listen on '%s'", WebListen) + + tlsConfig := &tls.Config{MinVersion: tls.VersionTLS12} // for security reasons disable TLS 1.0/1.1 + + server := &http.Server{ + Addr: WebListen, + Handler: Handler, + ReadTimeout: ReadTimeout, // ReadTimeout is the maximum duration for reading the entire request, including the body. + WriteTimeout: WriteTimeout, // WriteTimeout is the maximum duration before timing out writes of the response. This includes processing time and is therefore the max time any HTTP function may take. + //IdleTimeout: IdleTimeout, // IdleTimeout is the maximum amount of time to wait for the next request when keep-alives are enabled. + TLSConfig: tlsConfig, + } + + if UseSSL { + // HTTPS + if err := server.ListenAndServeTLS(CertificateFile, CertificateKey); err != nil { + backend.LogError("startWebServer", "Error listening on '%s': %v\n", WebListen, err) + } + } else { + // HTTP + if err := server.ListenAndServe(); err != nil { + backend.LogError("startWebServer", "Error listening on '%s': %v\n", WebListen, err) + } + } +} + +// parseDuration is the same as time.ParseDuration without returning an error. Valid units are ms, s, m, h. For example "10s". +func parseDuration(input string) (result time.Duration) { + result, _ = time.ParseDuration(input) + return +} + +func redirect(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently) +} + +func webRedirect80(listen80 string) { + // redirect HTTP -> HTTPS + http.ListenAndServe(net.JoinHostPort(listen80, "80"), http.HandlerFunc(redirect)) +} + +func webGatewayHandler(w http.ResponseWriter, r *http.Request) { + http.Error(w, "404 page not found", http.StatusNotFound) +} diff --git a/Main.go b/Main.go index 6826594..6722c0a 100644 --- a/Main.go +++ b/Main.go @@ -24,6 +24,10 @@ var config struct { WebCertificateKey string `yaml:"WebCertificateKey"` // This is the private key. WebTimeoutRead string `yaml:"WebTimeoutRead"` // The maximum duration for reading the entire request, including the body. WebTimeoutWrite string `yaml:"WebTimeoutWrite"` // The maximum duration before timing out writes of the response. This includes processing time and is therefore the max time any HTTP function may take. + Redirect80 string `yaml:"Redirect80"` // Redirect 80 listen address. Empty if not used. + + // WebFiles is the directory holding all HTML and other files to be served by the server + WebFiles string `yaml:"WebFiles"` } func main() { @@ -49,7 +53,9 @@ func main() { backend.Stdout.Subscribe(os.Stdout) - //startWebGateway(backend, ) + go startWebGateway(backend) backend.Connect() + + select {} } diff --git a/README.md b/README.md index fd78a4c..254cec8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,21 @@ The config filename is hard-coded to `Config.yaml` and is created on the first r Todo. +## Static Pages + +Access to `/` will show a generic information page. + +The main functionality is to provide URLs in the format `/[blockchain public key]/[file hash]` and other variations (using a directory name instead of file hash). This page shall provide access to one or multiple files shared via a user's blockchain. Access shall include download, preview, and providing a native Peernet link. The blockchain public key may be the node ID or the peer ID. Currently only hex encoding is supported. + +Native Peernet linsk should start with the `peernet://` custom scheme. On Windows such links can be opened with a registered protocol handler. + +To provide the best user experience, those static pages shall be generated immediately and use JavaScript to dynamically load the requested resource using the embedded API. + ## API Todo. +## Cache + +Todo. A cache folder should temporarily cache requested files so that they are available faster. + diff --git a/go.mod b/go.mod index 39c8305..2815db3 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,20 @@ module github.com/PeernetOfficial/Cmd -go 1.18 +go 1.19 -require github.com/PeernetOfficial/core v0.0.0-20220329002833-346f38c61138 +require ( + github.com/PeernetOfficial/core v0.0.0-20220601150942-0e3e8dc9885c + github.com/gorilla/mux v1.8.0 +) require ( github.com/akrylysov/pogreb v0.10.1 // indirect github.com/enfipy/locker v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect - golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect - golang.org/x/net v0.0.0-20220325170049-de3da57026de // indirect - golang.org/x/sys v0.0.0-20220325203850-36772127a21f // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 3276ca1..7a59a99 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,25 @@ -github.com/PeernetOfficial/core v0.0.0-20220329002833-346f38c61138 h1:AhFNcWzqLU/LXRN4qsCkhX4+oH1LuJPCHBkvAYNDnMI= -github.com/PeernetOfficial/core v0.0.0-20220329002833-346f38c61138/go.mod h1:X2a4/PoJKp0UWnaUZRa6sg+TrMgyNp9b3hj7axyQRuE= +github.com/PeernetOfficial/core v0.0.0-20220601150942-0e3e8dc9885c h1:n+NGYHQulohXk//v2LYOgCVsbL9h5COupt+2ZhbtGqs= +github.com/PeernetOfficial/core v0.0.0-20220601150942-0e3e8dc9885c/go.mod h1:Ek4/3aKyKnA/KDSNe/yeorX5TA0fckpN7etZ+nCelGc= github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w= github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/enfipy/locker v1.1.0 h1:2zVJ0ky7cS1Vjs0x6OQWFiT2dSEiHrI5/O2KCz1fgGc= github.com/enfipy/locker v1.1.0/go.mod h1:uuj+dvWHECshK8rkHcw+ZOb9SLo16yc0Em/JGUqRqko= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= -golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20220325170049-de3da57026de h1:pZB1TWnKi+o4bENlbzAgLrEbY4RMYmUIRobMcSmfeYc= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sys v0.0.0-20220325203850-36772127a21f h1:TrmogKRsSOxRMJbLYGrB4SBbW+LJcEllYBLME5Zk5pU= -golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA= +golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= diff --git a/html/favicon.ico b/html/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1106e91c7636563b2c9f5afde463ea437c6cf3ff GIT binary patch literal 7406 zcmeHMX;4#F6h3SULh8d4T6&I1&y}003e!I}Qf8fuBW0SjSC40EeRiG7y6l*o_C_Q46u2=&PUg zy>a{&jO$K-#iWNx{bd;I`xW$>qcE)c7zVDs2Dq_I({#J$&ofNO=w`a^L^;K zxF7o3pMcKeGMJh&!!#bI@eWX(EJJJ|bmB2(nE;D%5P6qi;P2<5zx_#2pWOi6f9?kJ zWG`|o$mzuOz5?wZJ3w=86Y`3{ICdS^_y9RCAifT|PE{km4~9D4h5jqgLidG6#P7tl zR)fi)!F48)a|1N3TcPuW3}ZV87V{`_`oS=K0Y-biN8WSD+Xr1|)`4N@JPh4>6Gqfu zAbusN@GwsfAnpg~z0`txDgyPH^0E#~h-T;pxzKaKnv53kGk#f%wl6yBV=1m^&lpegt#h zj=BE@bAA|l+72Q29nAY)6FOsl$yN%lUF13bCXs}gFn`+tiZ4v|IKO!RuIA?E z74d6|t=VBJR&!r4HXea|30mPE_UbYTA>7k9uy`87?U#c2+}Ua1#wRpJa7V+5_urf2 zZuW)-Nm%5v+ZMfN!OAV+QEp-(oFT*o@VwM3)jxN_41!)uCg(KcfEn)=7&J9XhP~1O{)s4!v#7 zPFmEaIf>p>oh+wXbFB9#sxx~o9-vy2=*$V-X{s~znqyRBj;N2=b*1|3Myf3*N3YoR z;J z34f+Kl4wY6E90ai``RC~>qw#@iGCbbePq{XR~e|8 z8&hO^o+mrMT;>T85>)HSU87jLGK}v5p;#pkNM7b1fPVSH0?+=4IH6kr;mhmXZ-M&f z{YQVDP=>}C1D!u8HaR&tBSFTWiJ|_Kii!;tnJW@YqGoJ_`f&@?ibeIV04Kj(o|fm5 zOX`=b^YhCU1(G@9#m-?;e;r>a6e^^P(J#nyUV-|p`SFiQk;_9jI$uo(zbv*0Cs-Qp zw19(OSS>(*G>4zA&zDt3%H_pL9P^7xOH1qL^VT3e&Emi;&-WQX}ZKU(=d|^x}2bU!i?z(pM(G`J~@Y>YLH- z?`Rz}qCQG%9kZba`^S}7-<-mEE3vm(v?ei*UZcHc(zhpl>` zl6>;l9c$>1l+NSX=OAN0e()08CuE$HUYu04)CwWv+`#ad$VJw_`^Z?bI9fJe5K5ON zW2vw(E4?I$u0qD~Sp{+a;$;iTl4Kkckdv??n++g3F>`sQXhAIb`lA*R5)u-@a|qGq Hn1k~_3}lO> literal 0 HcmV?d00001 diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..506959b --- /dev/null +++ b/html/index.html @@ -0,0 +1,12 @@ + + + + + Peernet Web Gateway + + + +

This is a web gateway to access Peernet files on the legacy web. Why don't you try the native Peernet Browser?

+ + + \ No newline at end of file