Support custom content types
This commit is contained in:
parent
3cb855acfa
commit
cac10df2f6
4 changed files with 51 additions and 19 deletions
|
@ -18,6 +18,11 @@ Address to listen for connections on in the format of `interface:port`.
|
|||
|
||||
`:1965`
|
||||
|
||||
## Types
|
||||
|
||||
Content types may be defined by file extension. When a type is not defined for
|
||||
the requested file extension, content type is detected automatically.
|
||||
|
||||
## Hosts
|
||||
|
||||
Hosts are defined by their hostname followed by one or more paths to serve.
|
||||
|
@ -181,6 +186,10 @@ References:
|
|||
# Address to listen on
|
||||
listen: :1965
|
||||
|
||||
# Custom content types
|
||||
types:
|
||||
.json: application/json; charset=UTF-8
|
||||
|
||||
# Hosts and paths to serve
|
||||
hosts:
|
||||
default: # Default host configuration
|
||||
|
|
20
config.go
20
config.go
|
@ -68,6 +68,8 @@ type hostConfig struct {
|
|||
type serverConfig struct {
|
||||
Listen string
|
||||
|
||||
Types map[string]string
|
||||
|
||||
Hosts map[string]*hostConfig
|
||||
|
||||
DisableSize bool
|
||||
|
@ -108,6 +110,10 @@ func readconfig(configPath string) error {
|
|||
log.Fatal("listen address must be specified")
|
||||
}
|
||||
|
||||
if config.Types == nil {
|
||||
config.Types = make(map[string]string)
|
||||
}
|
||||
|
||||
if config.SaneEOL {
|
||||
newLine = "\n"
|
||||
} else {
|
||||
|
@ -126,6 +132,20 @@ func readconfig(configPath string) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Default content types
|
||||
if config.Types[".htm"] == "" {
|
||||
config.Types[".htm"] = htmlType
|
||||
}
|
||||
if config.Types[".html"] == "" {
|
||||
config.Types[".html"] = htmlType
|
||||
}
|
||||
if config.Types[".gmi"] == "" {
|
||||
config.Types[".gmi"] = geminiType
|
||||
}
|
||||
if config.Types[".gemini"] == "" {
|
||||
config.Types[".gemini"] = geminiType
|
||||
}
|
||||
|
||||
defaultHost := config.Hosts["default"]
|
||||
delete(config.Hosts, "default")
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/h2non/filetype"
|
||||
)
|
||||
|
@ -98,33 +97,35 @@ func serveFile(c net.Conn, serve *pathConfig, filePath string) {
|
|||
file, _ := os.Open(filePath)
|
||||
defer file.Close()
|
||||
|
||||
// Read file header
|
||||
buf := make([]byte, 261)
|
||||
n, _ := file.Read(buf)
|
||||
|
||||
// Write response header
|
||||
var contentType string
|
||||
if strings.HasSuffix(filePath, ".html") && strings.HasSuffix(filePath, ".htm") {
|
||||
contentType = "text/html; charset=utf-8"
|
||||
} else if strings.HasSuffix(filePath, ".txt") && strings.HasSuffix(filePath, ".text") {
|
||||
contentType = "text/plain; charset=utf-8"
|
||||
} else if !strings.HasSuffix(filePath, ".gmi") && !strings.HasSuffix(filePath, ".gemini") {
|
||||
kind, _ := filetype.Match(buf[:n])
|
||||
if kind != filetype.Unknown {
|
||||
// Read content type
|
||||
var (
|
||||
buf = make([]byte, 261)
|
||||
n int
|
||||
)
|
||||
contentType := config.Types[filepath.Ext(filePath)]
|
||||
if contentType == "" {
|
||||
n, _ = file.Read(buf)
|
||||
kind, err := filetype.Match(buf[:n])
|
||||
if err == nil && kind != filetype.Unknown && kind.MIME.Value != "" {
|
||||
contentType = kind.MIME.Value
|
||||
} else {
|
||||
contentType = plainType
|
||||
}
|
||||
}
|
||||
if contentType == "" {
|
||||
contentType = geminiType
|
||||
}
|
||||
|
||||
// Read file size
|
||||
size := int64(-1)
|
||||
info, err := file.Stat()
|
||||
if err == nil {
|
||||
size = info.Size()
|
||||
}
|
||||
|
||||
// Write response header
|
||||
writeSuccess(c, serve, contentType, size)
|
||||
|
||||
// Write body
|
||||
c.Write(buf[:n])
|
||||
// Write file contents
|
||||
if n > 0 {
|
||||
c.Write(buf[:n])
|
||||
}
|
||||
io.Copy(c, file)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ const (
|
|||
|
||||
urlMaxLength = 1024
|
||||
|
||||
plainType = "text/plain; charset=utf-8"
|
||||
geminiType = "text/gemini; charset=utf-8"
|
||||
htmlType = "text/html; charset=utf-8"
|
||||
|
||||
logTimeFormat = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue