Add SaneEOL configuration option
This commit is contained in:
parent
0b744eba7e
commit
e3aeb18053
6 changed files with 41 additions and 14 deletions
|
@ -119,16 +119,31 @@ specified address or path.
|
|||
|
||||
A `Root` attribute must also be specified to use `FastCGI`.
|
||||
|
||||
## End-of-line indicator
|
||||
|
||||
The Gemini protocol requires `\r\n` (CRLF) as the end-of-line indicator. This
|
||||
convention is carried over from protocol specifications **first written in the
|
||||
1970s**. This requirement is antithetic to the spirit of Gemini (to improve
|
||||
upon the Finger and Gopher protocols) because it unnecessarily tacks on ancient
|
||||
baggage. This baggage has caused (and continues to cause) increased complexity in
|
||||
client and server implementations, which naturally gives rise to more bugs.
|
||||
|
||||
In anticipation of an improvement to the Gemini specification, administrators
|
||||
may configure twins to send standard `\n` (LF) line endings by setting
|
||||
`SaneEOL` to `true`.
|
||||
|
||||
References:
|
||||
[1](https://lists.orbitalfox.eu/archives/gemini/2019/000131.html)
|
||||
[2](https://lists.orbitalfox.eu/archives/gemini/2020/000756.html)
|
||||
[3](https://lists.orbitalfox.eu/archives/gemini/2020/001339.html)
|
||||
[4](https://lists.orbitalfox.eu/archives/gemini/2020/003065.html)
|
||||
|
||||
# Example config.yaml
|
||||
|
||||
```yaml
|
||||
# Address to listen on
|
||||
listen: :1965
|
||||
|
||||
# TLS certificates
|
||||
certificates:
|
||||
-
|
||||
|
||||
# Hosts and paths to serve
|
||||
hosts:
|
||||
gemini.rocks:
|
||||
|
|
|
@ -12,7 +12,7 @@ This page is also available at [gemini://twins.rocketnine.space](gemini://twins.
|
|||
## Features
|
||||
|
||||
- Serve static files
|
||||
- Directory listing (when enabled)
|
||||
- List files and directories (when enabled)
|
||||
- Reverse proxy requests
|
||||
- TCP
|
||||
- [FastCGI](https://en.wikipedia.org/wiki/FastCGI)
|
||||
|
|
|
@ -59,6 +59,8 @@ type serverConfig struct {
|
|||
|
||||
DisableSize bool
|
||||
|
||||
SaneEOL bool
|
||||
|
||||
hostname string
|
||||
port int
|
||||
fcgiPools map[string]gofast.ConnFactory
|
||||
|
@ -91,6 +93,12 @@ func readconfig(configPath string) error {
|
|||
log.Fatal("listen address must be specified")
|
||||
}
|
||||
|
||||
if config.SaneEOL {
|
||||
newLine = "\n"
|
||||
} else {
|
||||
newLine = "\r\n"
|
||||
}
|
||||
|
||||
split := strings.Split(config.Listen, ":")
|
||||
if len(split) != 2 {
|
||||
config.hostname = config.Listen
|
||||
|
|
|
@ -52,7 +52,7 @@ func serveDirList(c net.Conn, request *url.URL, dirPath string) {
|
|||
|
||||
writeHeader(c, statusSuccess, "text/gemini; charset=utf-8")
|
||||
|
||||
fmt.Fprintf(c, "# %s\r\n", request.Path)
|
||||
fmt.Fprintf(c, "# %s%s", request.Path, newLine)
|
||||
if numDirs == 1 {
|
||||
c.Write([]byte("1 directory"))
|
||||
} else {
|
||||
|
@ -64,10 +64,10 @@ func serveDirList(c net.Conn, request *url.URL, dirPath string) {
|
|||
} else {
|
||||
fmt.Fprintf(c, "%d files", numFiles)
|
||||
}
|
||||
c.Write([]byte("\r\n\n"))
|
||||
c.Write([]byte(newLine + newLine))
|
||||
|
||||
if request.Path != "/" {
|
||||
c.Write([]byte("=> ../ ../\r\n\r\n"))
|
||||
c.Write([]byte("=> ../ ../" + newLine + newLine))
|
||||
}
|
||||
|
||||
for _, info := range files {
|
||||
|
@ -78,10 +78,10 @@ func serveDirList(c net.Conn, request *url.URL, dirPath string) {
|
|||
filePath += "/"
|
||||
}
|
||||
|
||||
c.Write([]byte("=> " + fileName + " " + filePath + "\r\n"))
|
||||
c.Write([]byte("=> " + fileName + " " + filePath + newLine))
|
||||
|
||||
if info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
|
||||
c.Write([]byte("\r\n"))
|
||||
c.Write([]byte(newLine))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ func serveDirList(c net.Conn, request *url.URL, dirPath string) {
|
|||
if !info.ModTime().IsZero() {
|
||||
modified = info.ModTime().Format("2006-01-02 3:04 PM")
|
||||
}
|
||||
c.Write([]byte(modified + " - " + formatFileSize(info.Size()) + "\r\n\r\n"))
|
||||
c.Write([]byte(modified + " - " + formatFileSize(info.Size()) + newLine + newLine))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func serveProxy(c net.Conn, request *url.URL, proxyURL string) {
|
|||
|
||||
// Forward request
|
||||
proxy.Write([]byte(request.String()))
|
||||
proxy.Write([]byte("\r\n"))
|
||||
proxy.Write([]byte(newLine))
|
||||
|
||||
// Forward response
|
||||
io.Copy(c, proxy)
|
||||
|
|
|
@ -47,8 +47,10 @@ const (
|
|||
|
||||
var slashesRegexp = regexp.MustCompile(`[^\\]\/`)
|
||||
|
||||
var newLine = "\r\n"
|
||||
|
||||
func writeHeader(c net.Conn, code int, meta string) {
|
||||
fmt.Fprintf(c, "%d %s\r\n", code, meta)
|
||||
fmt.Fprintf(c, "%d %s%s", code, meta, newLine)
|
||||
|
||||
if verbose {
|
||||
log.Printf("< %d %s\n", code, meta)
|
||||
|
@ -203,7 +205,9 @@ func servePath(c *tls.Conn, request *url.URL, serve *pathConfig) {
|
|||
func serveConn(c *tls.Conn) {
|
||||
var requestData string
|
||||
scanner := bufio.NewScanner(c)
|
||||
scanner.Split(scanCRLF)
|
||||
if !config.SaneEOL {
|
||||
scanner.Split(scanCRLF)
|
||||
}
|
||||
if scanner.Scan() {
|
||||
requestData = scanner.Text()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue