initial commit
commit
dc76cbe5f1
|
@ -0,0 +1,65 @@
|
|||
// package scgi contains a minimal gemini SCGI framework
|
||||
package scgi
|
||||
|
||||
import (
|
||||
"net"
|
||||
"bufio"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SCGIHeaders is a map representing the headers of an SCGI request.
|
||||
type SCGIHeaders map[string]string
|
||||
|
||||
|
||||
// HandlerFunc is the type for a function that will handle an SCGI request
|
||||
type HandlerFunc func(net.Conn, SCGIHeaders) error
|
||||
|
||||
|
||||
// handle gets an SCGI request, parses it, and then lets fn handle the response
|
||||
func handle(c net.Conn, fn HandlerFunc) {
|
||||
defer c.Close() // Connection has to be closed for gemini
|
||||
reader := bufio.NewReader(c)
|
||||
hl, err := reader.ReadString(':') // SCGI Spec: First bytes until a ':' represent the header length
|
||||
if err != nil {
|
||||
c.Write([]byte("42" + err.Error()))
|
||||
return
|
||||
}
|
||||
l, err := strconv.Atoi(hl[:len(hl)-1]) // Strip the trailing :
|
||||
if err != nil {
|
||||
c.Write([]byte("42" + err.Error()))
|
||||
return
|
||||
}
|
||||
buf := make([]byte, l)
|
||||
_, err = reader.Read(buf)
|
||||
if err != nil {
|
||||
c.Write([]byte("42" + err.Error()))
|
||||
return
|
||||
}
|
||||
headerString := string(buf[:l])
|
||||
headerData := strings.Split(headerString, "\x00") // split on NULLs
|
||||
header := make(SCGIHeaders)
|
||||
// convert header data (a slice) to a map
|
||||
for i := 0; i < len(headerData); i +=2 {
|
||||
if headerData[i] != "" {
|
||||
header[headerData[i]] = headerData[i+1]
|
||||
}
|
||||
}
|
||||
err = fn(c, header)
|
||||
if err != nil {
|
||||
c.Write([]byte("42" + err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Serve runs a simple SCGI server on listener, handling requests with fn
|
||||
func Serve(listener net.Listener, fn HandlerFunc) error {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go handle(conn, fn)
|
||||
}
|
||||
}
|
Reference in New Issue