nandi/oripublic Fork 0
b6cd929ab1425a4ef6073ea9c189917cca02cf3c
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

✨ Switch the ACP adapter to @agentclientprotocol/claude-agent-acp (template 0.0.2) 5d476ff · on b6cd929ab1425a4ef6073ea9c189917cca02cf3c · k33g · 19h ago
raw.go · 94 lines · 2.8 KBGo Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package files

import (
	"mime"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// imageTypes pins the Content-Type of the image formats the preview pane
// renders, independently of the host's mime database (which may lack
// entries such as .webp or .avif, or spell .ico differently).
var imageTypes = map[string]string{
	".avif": "image/avif",
	".bmp":  "image/bmp",
	".gif":  "image/gif",
	".ico":  "image/x-icon",
	".jpeg": "image/jpeg",
	".jpg":  "image/jpeg",
	".png":  "image/png",
	".svg":  "image/svg+xml",
	".webp": "image/webp",
}

// textTypes pins the text formats the preview pane renders itself, for the
// same reason as imageTypes: Go seeds its mime table from the host (macOS's
// /etc/apache2/mime.types leaves text/markdown commented out), so without a
// pin a .md file is served as text/plain on one machine and text/markdown on
// another.
var textTypes = map[string]string{
	".markdown": "text/markdown; charset=utf-8",
	".md":       "text/markdown; charset=utf-8",
}

// ContentTypeFor returns the Content-Type the raw endpoint serves a file
// under: pinned image and text types first, then the host mime database, and
// a content sniff of the first bytes as a last resort.
//
// Example:
//
//	files.ContentTypeFor("logo.webp", nil) // "image/webp"
//	files.ContentTypeFor("README.md", nil) // "text/markdown; charset=utf-8"
func ContentTypeFor(path string, head []byte) string {
	ext := strings.ToLower(filepath.Ext(path))
	if typ, ok := imageTypes[ext]; ok {
		return typ
	}
	if typ, ok := textTypes[ext]; ok {
		return typ
	}
	if typ := mime.TypeByExtension(ext); typ != "" {
		return typ
	}
	return http.DetectContentType(head)
}

// rawFile streams a file's bytes as-is, for the browser to render (images)
// or download. Unlike readFile it has no size cap and no text requirement:
// http.ServeContent streams and honours Range requests.
func (s *Service) rawFile(w http.ResponseWriter, r *http.Request) {
	if r.URL.Query().Get("path") == "" {
		writeError(w, http.StatusBadRequest, "path query parameter is required")
		return
	}
	path := s.resolve(r.URL.Query().Get("path"))
	info, err := os.Stat(path)
	if err != nil {
		writeFSError(w, err)
		return
	}
	if info.IsDir() {
		writeError(w, http.StatusBadRequest, "path is a directory")
		return
	}
	file, err := os.Open(path)
	if err != nil {
		writeFSError(w, err)
		return
	}
	// Read-only handle: a Close error carries no information the client
	// could act on, and the response headers are already committed.
	defer func() { _ = file.Close() }()

	head := make([]byte, 512)
	n, _ := file.Read(head)
	if _, err := file.Seek(0, 0); err != nil {
		writeFSError(w, err)
		return
	}
	w.Header().Set("Content-Type", ContentTypeFor(path, head[:n]))
	w.Header().Set("X-Content-Type-Options", "nosniff")
	http.ServeContent(w, r, info.Name(), info.ModTime(), file)
}