4 files changed,
35 insertions(+),
18 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-03-09 18:21:37 +0200
Authored at:
2026-03-09 18:20:03 +0200
Change ID:
zoxtzxxqlvrnzxzrzoxmwmyxnvtrosqr
Parent:
bdfa44c
M
internal/handlers/handlers.go
··· 46 46 mux.HandleFunc("GET /{name}/feed/{$}", h.repoFeedHandler) 47 47 mux.HandleFunc("GET /{name}/tree/{ref}/{rest...}", h.repoTreeHandler) 48 48 mux.HandleFunc("GET /{name}/blob/{ref}/{rest...}", h.fileContentsHandler) 49 + mux.HandleFunc("GET /{name}/raw/{ref}/{rest...}", h.rawFileContentsHandler) 49 50 mux.HandleFunc("GET /{name}/log/{ref}", h.logHandler) 50 51 mux.HandleFunc("GET /{name}/commit/{ref}", h.commitHandler) 51 52 mux.HandleFunc("GET /{name}/refs/{$}", h.refsHandler)
M
internal/handlers/repo.go
··· 11 11 "os" 12 12 "path/filepath" 13 13 "sort" 14 - "strconv" 15 14 "strings" 16 15 "time" 17 16 ··· 177 176 ref := h.parseRef(r.PathValue("ref")) 178 177 treePath := r.PathValue("rest") 179 178 180 - var raw bool 181 - if rawParam, err := strconv.ParseBool(r.URL.Query().Get("raw")); err == nil { 182 - raw = rawParam 183 - } 184 - 185 179 repo, err := h.openPublicRepo(name, ref) 186 180 if err != nil { 187 181 h.write404(w, err) ··· 195 189 return 196 190 } 197 191 h.write500(w, err) 198 - return 199 - } 200 - 201 - if raw { 202 - w.Header().Set("Content-Type", fc.Mime) 203 - w.WriteHeader(http.StatusOK) 204 - w.Write(fc.Content) 205 192 return 206 193 } 207 194 ··· 236 223 } 237 224 238 225 h.templ(w, "repo_file", h.pageData(repo, p)) 226 +} 227 + 228 +func (h *handlers) rawFileContentsHandler(w http.ResponseWriter, r *http.Request) { 229 + name := r.PathValue("name") 230 + ref := h.parseRef(r.PathValue("ref")) 231 + treePath := r.PathValue("rest") 232 + 233 + repo, err := h.openPublicRepo(name, ref) 234 + if err != nil { 235 + w.WriteHeader(http.StatusNotFound) 236 + slog.Info("404", "err", err) 237 + return 238 + } 239 + 240 + fc, err := repo.FileContent(treePath) 241 + if err != nil { 242 + if errors.Is(err, git.ErrFileNotFound) { 243 + w.WriteHeader(http.StatusNotFound) 244 + slog.Info("404", "err", err) 245 + return 246 + } 247 + 248 + w.WriteHeader(http.StatusInternalServerError) 249 + slog.Info("500", "err", err) 250 + return 251 + } 252 + 253 + w.Header().Set("Content-Type", fc.Mime) 254 + w.WriteHeader(http.StatusOK) 255 + w.Write(fc.Content) 239 256 } 240 257 241 258 type RepoLog struct {
M
internal/markdown/relink.go
··· 87 87 } 88 88 89 89 absPath := m.path(dst) 90 - return path.Join("/", url.PathEscape(m.repoName), "blob", m.repoRef, absPath) + 91 - "?raw=true" 90 + return path.Join("/", url.PathEscape(m.repoName), "raw", m.repoRef, absPath) 92 91 } 93 92 94 93 func (m *relLinkTransformer) path(dst string) string {
M
web/templates/repo_file.html
··· 14 14 {{- if .IsLast -}}{{- .Name -}} 15 15 {{- else -}}<a class="link" href="/{{ $.RepoName }}/tree/{{ $.P.Ref }}/{{ .Path }}">{{ .Name }}</a>{{- end -}} 16 16 {{- end -}} 17 - (<a class="muted" href="?raw=true">view raw</a>) 17 + (<a class="muted" href="/{{ .RepoName }}/raw/{{ .P.Ref }}/{{ .P.Path }}">view raw</a>) 18 18 </p> 19 19 <div class="file-wrapper"> 20 20 {{ if .P.IsImage }} 21 21 <div class="image-viewer"> 22 22 <p>{{ .P.Mime }} • {{ .P.Size }} bytes</p> 23 - <img src="?raw=true" alt="{{- .P.Path -}}"> 23 + <img src="/{{ .RepoName }}/raw/{{ .P.Ref }}/{{ .P.Path }}" alt="{{- .P.Path -}}"> 24 24 </div> 25 25 {{ else if .P.IsBinary }} 26 26 <div class="binary-viewer"> 27 27 <p>Binary file ({{ .P.Mime }})</p> 28 28 <p>Size: {{ .P.Size }} bytes</p> 29 - <a class="link" href="?raw=true" download>[ Download ]</a> 29 + <a class="link" href="/{{ .RepoName }}/raw/{{ .P.Ref }}/{{ .P.Path }}" download>[ Download ]</a> 30 30 </div> 31 31 {{ else }} 32 32 <table>