mirror of
https://code.rocketnine.space/tslocum/twins.git
synced 2024-11-27 11:38:14 +01:00
Support redirecting to path or URL
This commit is contained in:
parent
58a4ecd958
commit
c64a59c44e
4 changed files with 62 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
47
config.go
47
config.go
|
@ -22,8 +22,9 @@ type pathConfig struct {
|
|||
|
||||
// Resource to serve
|
||||
Root string
|
||||
Proxy 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
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…
Reference in a new issue