Big rearrange: resolve URL to filesystem earlier, so we can check for .molly files ASAP, so that they can handle redirects, certificate zones, etc.
This commit is contained in:
parent
990b7071d0
commit
e43fc7877c
1 changed files with 39 additions and 33 deletions
72
handler.go
72
handler.go
|
@ -74,6 +74,14 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve URI path to actual filesystem path
|
||||||
|
path := resolvePath(URL.Path, config)
|
||||||
|
|
||||||
|
// Read Molly files
|
||||||
|
if config.ReadMollyFiles {
|
||||||
|
parseMollyFiles(path, &config, errorLogEntries)
|
||||||
|
}
|
||||||
|
|
||||||
// Check for redirects
|
// Check for redirects
|
||||||
for src, dst := range config.TempRedirects {
|
for src, dst := range config.TempRedirects {
|
||||||
if URL.Path == src {
|
if URL.Path == src {
|
||||||
|
@ -120,6 +128,22 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether this URL is in a configured CGI path
|
||||||
|
for _, cgiPath := range config.CGIPaths {
|
||||||
|
inCGIPath, err := regexp.Match(cgiPath, []byte(path))
|
||||||
|
if err != nil || !inCGIPath {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info.Mode().Perm()&0111 == 0111 {
|
||||||
|
handleCGI(config, path, URL, &log, errorLogEntries, conn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether this URL is mapped to an SCGI app
|
// Check whether this URL is mapped to an SCGI app
|
||||||
for scgi_url, scgi_socket := range config.SCGIPaths {
|
for scgi_url, scgi_socket := range config.SCGIPaths {
|
||||||
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
|
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
|
||||||
|
@ -129,10 +153,8 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve URI path to actual filesystem path
|
|
||||||
path, info, err := resolvePath(URL.Path, config)
|
|
||||||
|
|
||||||
// Fail if file does not exist or perms aren't right
|
// Fail if file does not exist or perms aren't right
|
||||||
|
info, err := os.Stat(path)
|
||||||
if os.IsNotExist(err) || os.IsPermission(err) {
|
if os.IsNotExist(err) || os.IsPermission(err) {
|
||||||
conn.Write([]byte("51 Not found!\r\n"))
|
conn.Write([]byte("51 Not found!\r\n"))
|
||||||
log.Status = 51
|
log.Status = 51
|
||||||
|
@ -162,11 +184,6 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Molly files
|
|
||||||
if config.ReadMollyFiles {
|
|
||||||
parseMollyFiles(path, info, &config, errorLogEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle directories
|
// Handle directories
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
// Redirect to add trailing slash if missing
|
// Redirect to add trailing slash if missing
|
||||||
|
@ -190,17 +207,6 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this file is executable, get dynamic content
|
|
||||||
if info.Mode().Perm()&0111 == 0111 {
|
|
||||||
for _, cgiPath := range config.CGIPaths {
|
|
||||||
inCGIPath, err := regexp.Match(cgiPath, []byte(path))
|
|
||||||
if err == nil && inCGIPath {
|
|
||||||
handleCGI(config, path, URL, &log, errorLogEntries, conn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, serve the file contents
|
// Otherwise, serve the file contents
|
||||||
serveFile(path, &log, conn, config, errorLogEntries)
|
serveFile(path, &log, conn, config, errorLogEntries)
|
||||||
return
|
return
|
||||||
|
@ -239,7 +245,7 @@ func readRequest(conn net.Conn, log *LogEntry, errorLog chan string) (*url.URL,
|
||||||
return URL, nil
|
return URL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolvePath(path string, config Config) (string, os.FileInfo, error) {
|
func resolvePath(path string, config Config) string {
|
||||||
// Handle tildes
|
// Handle tildes
|
||||||
if strings.HasPrefix(path, "/~") {
|
if strings.HasPrefix(path, "/~") {
|
||||||
bits := strings.Split(path, "/")
|
bits := strings.Split(path, "/")
|
||||||
|
@ -250,20 +256,12 @@ func resolvePath(path string, config Config) (string, os.FileInfo, error) {
|
||||||
} else {
|
} else {
|
||||||
path = filepath.Join(config.DocBase, path)
|
path = filepath.Join(config.DocBase, path)
|
||||||
}
|
}
|
||||||
// Make sure this file exists and is readable
|
return path
|
||||||
info, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
return path, info, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMollyFiles(path string, info os.FileInfo, config *Config, errorLogEntries chan string) {
|
func parseMollyFiles(path string, config *Config, errorLogEntries chan string) {
|
||||||
// Build list of directories to check
|
// Build list of directories to check
|
||||||
dirs := make([]string, 16)
|
var dirs []string
|
||||||
if !info.IsDir() {
|
|
||||||
path = filepath.Dir(path)
|
|
||||||
}
|
|
||||||
dirs = append(dirs, path)
|
dirs = append(dirs, path)
|
||||||
for {
|
for {
|
||||||
if path == filepath.Clean(config.DocBase) {
|
if path == filepath.Clean(config.DocBase) {
|
||||||
|
@ -280,14 +278,22 @@ func parseMollyFiles(path string, info os.FileInfo, config *Config, errorLogEntr
|
||||||
mollyFile.DirectorySort = config.DirectorySort
|
mollyFile.DirectorySort = config.DirectorySort
|
||||||
mollyFile.DirectoryReverse = config.DirectoryReverse
|
mollyFile.DirectoryReverse = config.DirectoryReverse
|
||||||
mollyFile.DirectoryTitles = config.DirectoryTitles
|
mollyFile.DirectoryTitles = config.DirectoryTitles
|
||||||
// Parse files
|
// Parse files in reverse order
|
||||||
for i := len(dirs) - 1; i >= 0; i-- {
|
for i := len(dirs) - 1; i >= 0; i-- {
|
||||||
dir := dirs[i]
|
dir := dirs[i]
|
||||||
|
fmt.Println("Considering " + dir)
|
||||||
|
// Break out of the loop if a directory doesn't exist
|
||||||
|
_, err := os.Stat(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Construct path for a .molly file in this dir
|
||||||
mollyPath := filepath.Join(dir, ".molly")
|
mollyPath := filepath.Join(dir, ".molly")
|
||||||
_, err := os.Stat(mollyPath)
|
_, err = os.Stat(mollyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// If the file exists and we can read it, try to parse it
|
||||||
_, err = toml.DecodeFile(mollyPath, &mollyFile)
|
_, err = toml.DecodeFile(mollyPath, &mollyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorLogEntries <- "Error parsing .molly file " + mollyPath + ": " + err.Error()
|
errorLogEntries <- "Error parsing .molly file " + mollyPath + ": " + err.Error()
|
||||||
|
|
Loading…
Reference in a new issue