Browse Source

Support redirecting to path or URL

master
Trevor Slocum 2 years ago
parent
commit
c64a59c44e
  1. 22
      CONFIGURATION.md
  2. 1
      README.md
  3. 51
      config.go
  4. 22
      server.go

22
CONFIGURATION.md

@ -87,12 +87,6 @@ One resource must be defined for each path.
Serve static files from specified root directory.
##### Proxy
Forward requests to Gemini server at specified URL.
Use the pseudo-scheme `gemini-insecure://` to disable certificate verification.
##### Command
Serve output of system command.
@ -101,6 +95,16 @@ When input is requested from the user, it is available as a pseudo-variable
`$USERINPUT` which does not require surrounding quotes. It may be used as an
argument to the command, otherwise user input is passed via standard input.
##### Proxy
Forward requests to Gemini server at specified URL.
Use the pseudo-scheme `gemini-insecure://` to disable certificate verification.
##### Redirect
Redirect requests to specified path or URL.
#### Attributes
Any number of attributes may be defined for a path.
@ -220,6 +224,12 @@ hosts:
path: ^/cmd-example$
command: uname -a
cache: 0 # Do not cache
-
path: /redir-path-example
redirect: /other-resource
-
path: /redir-url-example
redirect: gemini://gemini.circumlunar.space/
-
path: /
root: /home/geminirocks/data/home

1
README.md

@ -19,6 +19,7 @@ This page is also available at [gemini://twins.rocketnine.space](gemini://twins.
- TCP
- [FastCGI](https://en.wikipedia.org/wiki/FastCGI)
- Serve system command output
- Redirect to path or URL
- Reload configuration on `SIGHUP`
## Proposals

51
config.go

@ -21,9 +21,10 @@ type pathConfig struct {
Path string
// Resource to serve
Root string
Proxy string
Command string
Root string
Command string
Proxy string
Redirect string
// Request input
Input string
@ -164,12 +165,12 @@ func readconfig(configPath string) error {
if defaultPath.Root != "" && serve.Root == "" {
serve.Root = defaultPath.Root
}
if defaultPath.Proxy != "" && serve.Proxy == "" {
serve.Proxy = defaultPath.Proxy
}
if defaultPath.Command != "" && serve.Command == "" {
serve.Command = defaultPath.Command
}
if defaultPath.Proxy != "" && serve.Proxy == "" {
serve.Proxy = defaultPath.Proxy
}
if defaultPath.SymLinks {
serve.SymLinks = defaultPath.SymLinks
}
@ -206,17 +207,31 @@ func readconfig(configPath string) error {
for _, serve := range host.Paths {
if serve.Path == "" {
log.Fatal("path must be specified in serve entry")
} else if (serve.Root != "" && (serve.Proxy != "" || serve.Command != "")) ||
(serve.Proxy != "" && (serve.Root != "" || serve.Command != "")) ||
(serve.Command != "" && (serve.Root != "" || serve.Proxy != "")) {
log.Fatal("only one root, proxy or command resource may specified for a path")
log.Fatal("a path must be specified in each serve entry")
}
if serve.Path[0] == '^' {
serve.r = regexp.MustCompile(serve.Path)
}
var resources int
if serve.Root != "" {
resources++
}
if serve.Command != "" {
resources++
}
if serve.Proxy != "" {
resources++
}
if serve.Redirect != "" {
resources++
}
if resources == 0 {
log.Fatalf("a resource must specified for path %s%s", hostname, serve.Path)
} else if resources > 1 {
log.Fatalf("only one resource (root, command, proxy or redirect) may specified for path %s%s", hostname, serve.Path)
}
serve.cache = cacheUnset
if serve.Cache != "" {
serve.cache, err = strconv.ParseInt(serve.Cache, 10, 64)
@ -225,7 +240,12 @@ func readconfig(configPath string) error {
}
}
if serve.FastCGI != "" {
if serve.Command != "" {
serve.cmd, err = shellquote.Split(serve.Command)
if err != nil {
log.Fatalf("failed to parse command %s: %s", serve.cmd, err)
}
} else if serve.FastCGI != "" {
if serve.Root == "" {
log.Fatalf("root must be specified to use fastcgi resource %s of path %s%s", serve.FastCGI, hostname, serve.Path)
}
@ -238,11 +258,6 @@ func readconfig(configPath string) error {
config.fcgiPools[serve.FastCGI] = gofast.SimpleConnFactory(f.Scheme, f.Host+f.Path)
}
} else if serve.Command != "" {
serve.cmd, err = shellquote.Split(serve.Command)
if err != nil {
log.Fatalf("failed to parse command %s: %s", serve.cmd, err)
}
}
}
}

22
server.go

@ -174,7 +174,16 @@ func servePath(c *tls.Conn, request *url.URL, serve *pathConfig) (int, int64) {
filePath = path.Join(root, resolvedPath)
}
if serve.Proxy != "" {
if serve.cmd != nil {
requireInput := serve.Input != "" || serve.SensitiveInput != ""
if requireInput {
newCommand := replaceWithUserInput(serve.cmd, request)
if newCommand != nil {
return serveCommand(c, serve, request, newCommand)
}
}
return serveCommand(c, serve, request, serve.cmd)
} else if serve.Proxy != "" {
return serveProxy(c, request, serve.Proxy), -1
} else if serve.FastCGI != "" {
if filePath == "" {
@ -189,15 +198,8 @@ func servePath(c *tls.Conn, request *url.URL, serve *pathConfig) (int, int64) {
serveFastCGI(c, config.fcgiPools[serve.FastCGI], request, filePath)
return statusSuccess, -1
} else if serve.cmd != nil {
requireInput := serve.Input != "" || serve.SensitiveInput != ""
if requireInput {
newCommand := replaceWithUserInput(serve.cmd, request)
if newCommand != nil {
return serveCommand(c, serve, request, newCommand)
}
}
return serveCommand(c, serve, request, serve.cmd)
} else if serve.Redirect != "" {
return writeHeader(c, statusRedirectTemporary, serve.Redirect), -1
}
if filePath == "" {

Loading…
Cancel
Save