commit inicial
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