commit inicial
This commit is contained in:
commit
51a832af15
|
@ -0,0 +1,30 @@
|
||||||
|
CHAOTIC SOFTWARE : BEWARE
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Don't expect support, ongoing development, or maintenance. side effects
|
||||||
|
may include uncomfortable clarity, dry mouth, and/or spiritual revolt.
|
||||||
|
For your own sanity, PLEASE FORK NOW!
|
||||||
|
|
||||||
|
For more information, please refer to <gemini://xj-ix.luxe/wiki/chaotic-software/>
|
|
@ -0,0 +1,18 @@
|
||||||
|
# chamorrx
|
||||||
|
|
||||||
|
pequeño servidor gemini en go
|
||||||
|
|
||||||
|
basado en el ejemplo de servidor de [go-gemini](https://git.sr.ht/~adnano/go-gemini) y algunos aspectos del servidor de [flounder](https://git.alexwennerberg.com/flounder/)
|
||||||
|
|
||||||
|
# config
|
||||||
|
|
||||||
|
el servidor espera una configuración con el siguiente formato, para indicar los hosts que existirán y desde dónde se servirán:
|
||||||
|
|
||||||
|
```
|
||||||
|
example.com /var/gemini/ejemplo
|
||||||
|
otrohost.com /var/gemini/otroejemplo
|
||||||
|
```
|
||||||
|
|
||||||
|
# licencia
|
||||||
|
|
||||||
|
> THIS IS CHAOTIC SOFTWARE BEWARE <gemini://sunshinegardens.org/~xj9/wiki/chaotic-software/>
|
|
@ -0,0 +1,10 @@
|
||||||
|
module chamorrx
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
require git.sr.ht/~adnano/go-gemini v0.2.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||||
|
golang.org/x/text v0.3.3 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
git.sr.ht/~adnano/go-gemini v0.2.2 h1:p2owKzrQ1wTgvPS5CZCPYArQyNUL8ZgYOHHrTjH9sdI=
|
||||||
|
git.sr.ht/~adnano/go-gemini v0.2.2/go.mod h1:hQ75Y0i5jSFL+FQ7AzWVAYr5LQsaFC7v3ZviNyj46dY=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
@ -0,0 +1,136 @@
|
||||||
|
// servidor gemini basado en el ejemplo de go-gemini y algo del código de flounder
|
||||||
|
// https://git.sr.ht/~adnano/go-gemini
|
||||||
|
// https://git.alexwennerberg.com/flounder/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.sr.ht/~adnano/go-gemini"
|
||||||
|
"git.sr.ht/~adnano/go-gemini/certificate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// de flounder: https://git.alexwennerberg.com/flounder/file/utils.go.html
|
||||||
|
func cleanPath(thepath string) string {
|
||||||
|
res := filepath.FromSlash(path.Clean("/" + strings.Trim(thepath, "/")))
|
||||||
|
if strings.Contains(res, "..") { // sanity check
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// mapa de hosts : directorios
|
||||||
|
var mapa map[string]string
|
||||||
|
|
||||||
|
// inspirada por gmiPage de flounder: https://git.alexwennerberg.com/flounder/file/gemini.go.html
|
||||||
|
func gmiHandler(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) {
|
||||||
|
|
||||||
|
fileName := cleanPath(r.URL.Path)
|
||||||
|
// obtiene el hostname sin el puerto
|
||||||
|
host := strings.SplitN(r.URL.Host, ":", 2)[0]
|
||||||
|
|
||||||
|
// utiliza el directorio indicado por el mapa
|
||||||
|
dir := mapa[host]
|
||||||
|
|
||||||
|
fullPath := path.Join(dir, fileName)
|
||||||
|
if strings.Contains(fileName, "atom.xml") {
|
||||||
|
_, err := os.Stat(fullPath)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
// inspirado de ServeFile en fs.go:
|
||||||
|
f, _ := os.Open(fullPath)
|
||||||
|
defer f.Close()
|
||||||
|
w.SetMediaType("application/atom+xml")
|
||||||
|
io.Copy(w, f)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gemini.ServeFile(w, os.DirFS(dir), fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
config, err := os.Open("config.txt")
|
||||||
|
|
||||||
|
log.Println("cargando configuración...")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer config.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(config)
|
||||||
|
mapa = make(map[string]string)
|
||||||
|
|
||||||
|
for scanner.Scan(){
|
||||||
|
campos := strings.SplitN( scanner.Text(), " ", 2 )
|
||||||
|
mapa[ campos[0] ] = campos[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("configuración cargada!")
|
||||||
|
|
||||||
|
log.Println("registrando certificados...")
|
||||||
|
|
||||||
|
certificates := &certificate.Store{}
|
||||||
|
|
||||||
|
for host,_ := range mapa {
|
||||||
|
certificates.Register(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := certificates.Load("certs"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("certificados listos!")
|
||||||
|
|
||||||
|
log.Println("iniciando servidor...")
|
||||||
|
mux := &gemini.Mux{}
|
||||||
|
mux.HandleFunc("/", gmiHandler)
|
||||||
|
|
||||||
|
server := &gemini.Server{
|
||||||
|
Addr: ":1965",
|
||||||
|
Handler: gemini.LoggingMiddleware(mux),
|
||||||
|
ReadTimeout: 30 * time.Second,
|
||||||
|
WriteTimeout: 1 * time.Minute,
|
||||||
|
GetCertificate: certificates.Get,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for interrupt signal
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, os.Interrupt)
|
||||||
|
|
||||||
|
errch := make(chan error)
|
||||||
|
go func() {
|
||||||
|
ctx := context.Background()
|
||||||
|
errch <- server.ListenAndServe(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-errch:
|
||||||
|
log.Fatal(err)
|
||||||
|
case <-c:
|
||||||
|
// Shutdown the server
|
||||||
|
log.Println("Shutting down...")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
err := server.Shutdown(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue