mirror of
https://github.com/filebrowser/filebrowser.git
synced 2026-01-23 02:35:10 +00:00
GOFMT
Former-commit-id: bbc11e551ed79fc41af61d67bfb9a882dfc8e655 [formerly 4ef42ee3251bdf613b7e24b50692629fbf8965ed] [formerly 10abcd7f0e34753069a80a683df94084f03fdb4b [formerly 1d4cbd622c]]
Former-commit-id: 7ac0c18ad61cd491f22b906e1efd87892d729cb2 [formerly b45c7e312058490ae90c8162e6cc1264613a9126]
Former-commit-id: 1c7e8ebd2f1b1dc5bd25df9f30a77c9b73ccad4d
This commit is contained in:
parent
b96a4a63c0
commit
3bb3fdb956
16 changed files with 2300 additions and 2300 deletions
688
http/http.go
688
http/http.go
|
|
@ -1,344 +1,344 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
fm "github.com/hacdias/filemanager"
|
||||
)
|
||||
|
||||
// Handler returns a function compatible with http.HandleFunc.
|
||||
func Handler(m *fm.FileManager) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
code, err := serve(&fm.Context{
|
||||
FileManager: m,
|
||||
User: nil,
|
||||
File: nil,
|
||||
}, w, r)
|
||||
|
||||
if code >= 400 {
|
||||
w.WriteHeader(code)
|
||||
|
||||
txt := http.StatusText(code)
|
||||
log.Printf("%v: %v %v\n", r.URL.Path, code, txt)
|
||||
w.Write([]byte(txt + "\n"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// serve is the main entry point of this HTML application.
|
||||
func serve(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
// Checks if the URL contains the baseURL and strips it. Otherwise, it just
|
||||
// returns a 404 fm.Error because we're not supposed to be here!
|
||||
p := strings.TrimPrefix(r.URL.Path, c.BaseURL)
|
||||
|
||||
if len(p) >= len(r.URL.Path) && c.BaseURL != "" {
|
||||
return http.StatusNotFound, nil
|
||||
}
|
||||
|
||||
r.URL.Path = p
|
||||
|
||||
// Check if this request is made to the service worker. If so,
|
||||
// pass it through a template to add the needed variables.
|
||||
if r.URL.Path == "/sw.js" {
|
||||
return renderFile(c, w, "sw.js")
|
||||
}
|
||||
|
||||
// Checks if this request is made to the static assets folder. If so, and
|
||||
// if it is a GET request, returns with the asset. Otherwise, returns
|
||||
// a status not implemented.
|
||||
if matchURL(r.URL.Path, "/static") {
|
||||
if r.Method != http.MethodGet {
|
||||
return http.StatusNotImplemented, nil
|
||||
}
|
||||
|
||||
return staticHandler(c, w, r)
|
||||
}
|
||||
|
||||
// Checks if this request is made to the API and directs to the
|
||||
// API handler if so.
|
||||
if matchURL(r.URL.Path, "/api") {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/api")
|
||||
return apiHandler(c, w, r)
|
||||
}
|
||||
|
||||
// If it is a request to the preview and a static website generator is
|
||||
// active, build the preview.
|
||||
if strings.HasPrefix(r.URL.Path, "/preview") && c.StaticGen != nil {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/preview")
|
||||
return c.StaticGen.Preview(c, w, r)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(r.URL.Path, "/share/") {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/share/")
|
||||
return sharePage(c, w, r)
|
||||
}
|
||||
|
||||
// Any other request should show the index.html file.
|
||||
w.Header().Set("x-frame-options", "SAMEORIGIN")
|
||||
w.Header().Set("x-content-type", "nosniff")
|
||||
w.Header().Set("x-xss-protection", "1; mode=block")
|
||||
|
||||
return renderFile(c, w, "index.html")
|
||||
}
|
||||
|
||||
// staticHandler handles the static assets path.
|
||||
func staticHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.URL.Path != "/static/manifest.json" {
|
||||
http.FileServer(c.Assets.HTTPBox()).ServeHTTP(w, r)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return renderFile(c, w, "static/manifest.json")
|
||||
}
|
||||
|
||||
// apiHandler is the main entry point for the /api endpoint.
|
||||
func apiHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.URL.Path == "/auth/get" {
|
||||
return authHandler(c, w, r)
|
||||
}
|
||||
|
||||
if r.URL.Path == "/auth/renew" {
|
||||
return renewAuthHandler(c, w, r)
|
||||
}
|
||||
|
||||
valid, _ := validateAuth(c, r)
|
||||
if !valid {
|
||||
return http.StatusForbidden, nil
|
||||
}
|
||||
|
||||
c.Router, r.URL.Path = splitURL(r.URL.Path)
|
||||
|
||||
if !c.User.Allowed(r.URL.Path) {
|
||||
return http.StatusForbidden, nil
|
||||
}
|
||||
|
||||
if c.StaticGen != nil {
|
||||
// If we are using the 'magic url' for the settings,
|
||||
// we should redirect the request for the acutual path.
|
||||
if r.URL.Path == "/settings" {
|
||||
r.URL.Path = c.StaticGen.SettingsPath()
|
||||
}
|
||||
|
||||
// Executes the Static website generator hook.
|
||||
code, err := c.StaticGen.Hook(c, w, r)
|
||||
if code != 0 || err != nil {
|
||||
return code, err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Router == "checksum" || c.Router == "download" {
|
||||
var err error
|
||||
c.File, err = fm.GetInfo(r.URL, c.FileManager, c.User)
|
||||
if err != nil {
|
||||
return ErrorToHTTP(err, false), err
|
||||
}
|
||||
}
|
||||
|
||||
var code int
|
||||
var err error
|
||||
|
||||
switch c.Router {
|
||||
case "download":
|
||||
code, err = downloadHandler(c, w, r)
|
||||
case "checksum":
|
||||
code, err = checksumHandler(c, w, r)
|
||||
case "command":
|
||||
code, err = command(c, w, r)
|
||||
case "search":
|
||||
code, err = search(c, w, r)
|
||||
case "resource":
|
||||
code, err = resourceHandler(c, w, r)
|
||||
case "users":
|
||||
code, err = usersHandler(c, w, r)
|
||||
case "settings":
|
||||
code, err = settingsHandler(c, w, r)
|
||||
case "share":
|
||||
code, err = shareHandler(c, w, r)
|
||||
default:
|
||||
code = http.StatusNotFound
|
||||
}
|
||||
|
||||
return code, err
|
||||
}
|
||||
|
||||
// serveChecksum calculates the hash of a file. Supports MD5, SHA1, SHA256 and SHA512.
|
||||
func checksumHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
query := r.URL.Query().Get("algo")
|
||||
|
||||
val, err := c.File.Checksum(query)
|
||||
if err == fm.ErrInvalidOption {
|
||||
return http.StatusBadRequest, err
|
||||
} else if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
w.Write([]byte(val))
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// splitURL splits the path and returns everything that stands
|
||||
// before the first slash and everything that goes after.
|
||||
func splitURL(path string) (string, string) {
|
||||
if path == "" {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
path = strings.TrimPrefix(path, "/")
|
||||
|
||||
i := strings.Index(path, "/")
|
||||
if i == -1 {
|
||||
return "", path
|
||||
}
|
||||
|
||||
return path[0:i], path[i:]
|
||||
}
|
||||
|
||||
// renderFile renders a file using a template with some needed variables.
|
||||
func renderFile(c *fm.Context, w http.ResponseWriter, file string) (int, error) {
|
||||
tpl := template.Must(template.New("file").Parse(c.Assets.MustString(file)))
|
||||
|
||||
var contentType string
|
||||
switch filepath.Ext(file) {
|
||||
case ".html":
|
||||
contentType = "text/html"
|
||||
case ".js":
|
||||
contentType = "application/javascript"
|
||||
case ".json":
|
||||
contentType = "application/json"
|
||||
default:
|
||||
contentType = "text"
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", contentType+"; charset=utf-8")
|
||||
|
||||
data := map[string]interface{}{
|
||||
"BaseURL": c.RootURL(),
|
||||
"NoAuth": c.NoAuth,
|
||||
"Version": fm.Version,
|
||||
"CSS": template.CSS(c.CSS),
|
||||
"ReCaptcha": c.ReCaptchaKey != "" && c.ReCaptchaSecret != "",
|
||||
"ReCaptchaKey": c.ReCaptchaKey,
|
||||
"ReCaptchaSecret": c.ReCaptchaSecret,
|
||||
}
|
||||
|
||||
if c.StaticGen != nil {
|
||||
data["StaticGen"] = c.StaticGen.Name()
|
||||
}
|
||||
|
||||
err := tpl.Execute(w, data)
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// sharePage build the share page.
|
||||
func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
s, err := c.Store.Share.Get(r.URL.Path)
|
||||
if err == fm.ErrNotExist {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return renderFile(c, w, "static/share/404.html")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
if s.Expires && s.ExpireDate.Before(time.Now()) {
|
||||
c.Store.Share.Delete(s.Hash)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return renderFile(c, w, "static/share/404.html")
|
||||
}
|
||||
|
||||
r.URL.Path = s.Path
|
||||
|
||||
info, err := os.Stat(s.Path)
|
||||
if err != nil {
|
||||
c.Store.Share.Delete(s.Hash)
|
||||
return ErrorToHTTP(err, false), err
|
||||
}
|
||||
|
||||
c.File = &fm.File{
|
||||
Path: s.Path,
|
||||
Name: info.Name(),
|
||||
ModTime: info.ModTime(),
|
||||
Mode: info.Mode(),
|
||||
IsDir: info.IsDir(),
|
||||
Size: info.Size(),
|
||||
}
|
||||
|
||||
dl := r.URL.Query().Get("dl")
|
||||
|
||||
if dl == "" || dl == "0" {
|
||||
tpl := template.Must(template.New("file").Parse(c.Assets.MustString("static/share/index.html")))
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
err := tpl.Execute(w, map[string]interface{}{
|
||||
"BaseURL": c.RootURL(),
|
||||
"File": c.File,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return downloadHandler(c, w, r)
|
||||
}
|
||||
|
||||
// renderJSON prints the JSON version of data to the browser.
|
||||
func renderJSON(w http.ResponseWriter, data interface{}) (int, error) {
|
||||
marsh, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if _, err := w.Write(marsh); err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// matchURL checks if the first URL matches the second.
|
||||
func matchURL(first, second string) bool {
|
||||
first = strings.ToLower(first)
|
||||
second = strings.ToLower(second)
|
||||
|
||||
return strings.HasPrefix(first, second)
|
||||
}
|
||||
|
||||
// ErrorToHTTP converts errors to HTTP Status Code.
|
||||
func ErrorToHTTP(err error, gone bool) int {
|
||||
switch {
|
||||
case err == nil:
|
||||
return http.StatusOK
|
||||
case os.IsPermission(err):
|
||||
return http.StatusForbidden
|
||||
case os.IsNotExist(err):
|
||||
if !gone {
|
||||
return http.StatusNotFound
|
||||
}
|
||||
|
||||
return http.StatusGone
|
||||
case os.IsExist(err):
|
||||
return http.StatusConflict
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
fm "github.com/hacdias/filemanager"
|
||||
)
|
||||
|
||||
// Handler returns a function compatible with http.HandleFunc.
|
||||
func Handler(m *fm.FileManager) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
code, err := serve(&fm.Context{
|
||||
FileManager: m,
|
||||
User: nil,
|
||||
File: nil,
|
||||
}, w, r)
|
||||
|
||||
if code >= 400 {
|
||||
w.WriteHeader(code)
|
||||
|
||||
txt := http.StatusText(code)
|
||||
log.Printf("%v: %v %v\n", r.URL.Path, code, txt)
|
||||
w.Write([]byte(txt + "\n"))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// serve is the main entry point of this HTML application.
|
||||
func serve(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
// Checks if the URL contains the baseURL and strips it. Otherwise, it just
|
||||
// returns a 404 fm.Error because we're not supposed to be here!
|
||||
p := strings.TrimPrefix(r.URL.Path, c.BaseURL)
|
||||
|
||||
if len(p) >= len(r.URL.Path) && c.BaseURL != "" {
|
||||
return http.StatusNotFound, nil
|
||||
}
|
||||
|
||||
r.URL.Path = p
|
||||
|
||||
// Check if this request is made to the service worker. If so,
|
||||
// pass it through a template to add the needed variables.
|
||||
if r.URL.Path == "/sw.js" {
|
||||
return renderFile(c, w, "sw.js")
|
||||
}
|
||||
|
||||
// Checks if this request is made to the static assets folder. If so, and
|
||||
// if it is a GET request, returns with the asset. Otherwise, returns
|
||||
// a status not implemented.
|
||||
if matchURL(r.URL.Path, "/static") {
|
||||
if r.Method != http.MethodGet {
|
||||
return http.StatusNotImplemented, nil
|
||||
}
|
||||
|
||||
return staticHandler(c, w, r)
|
||||
}
|
||||
|
||||
// Checks if this request is made to the API and directs to the
|
||||
// API handler if so.
|
||||
if matchURL(r.URL.Path, "/api") {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/api")
|
||||
return apiHandler(c, w, r)
|
||||
}
|
||||
|
||||
// If it is a request to the preview and a static website generator is
|
||||
// active, build the preview.
|
||||
if strings.HasPrefix(r.URL.Path, "/preview") && c.StaticGen != nil {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/preview")
|
||||
return c.StaticGen.Preview(c, w, r)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(r.URL.Path, "/share/") {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/share/")
|
||||
return sharePage(c, w, r)
|
||||
}
|
||||
|
||||
// Any other request should show the index.html file.
|
||||
w.Header().Set("x-frame-options", "SAMEORIGIN")
|
||||
w.Header().Set("x-content-type", "nosniff")
|
||||
w.Header().Set("x-xss-protection", "1; mode=block")
|
||||
|
||||
return renderFile(c, w, "index.html")
|
||||
}
|
||||
|
||||
// staticHandler handles the static assets path.
|
||||
func staticHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.URL.Path != "/static/manifest.json" {
|
||||
http.FileServer(c.Assets.HTTPBox()).ServeHTTP(w, r)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return renderFile(c, w, "static/manifest.json")
|
||||
}
|
||||
|
||||
// apiHandler is the main entry point for the /api endpoint.
|
||||
func apiHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.URL.Path == "/auth/get" {
|
||||
return authHandler(c, w, r)
|
||||
}
|
||||
|
||||
if r.URL.Path == "/auth/renew" {
|
||||
return renewAuthHandler(c, w, r)
|
||||
}
|
||||
|
||||
valid, _ := validateAuth(c, r)
|
||||
if !valid {
|
||||
return http.StatusForbidden, nil
|
||||
}
|
||||
|
||||
c.Router, r.URL.Path = splitURL(r.URL.Path)
|
||||
|
||||
if !c.User.Allowed(r.URL.Path) {
|
||||
return http.StatusForbidden, nil
|
||||
}
|
||||
|
||||
if c.StaticGen != nil {
|
||||
// If we are using the 'magic url' for the settings,
|
||||
// we should redirect the request for the acutual path.
|
||||
if r.URL.Path == "/settings" {
|
||||
r.URL.Path = c.StaticGen.SettingsPath()
|
||||
}
|
||||
|
||||
// Executes the Static website generator hook.
|
||||
code, err := c.StaticGen.Hook(c, w, r)
|
||||
if code != 0 || err != nil {
|
||||
return code, err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Router == "checksum" || c.Router == "download" {
|
||||
var err error
|
||||
c.File, err = fm.GetInfo(r.URL, c.FileManager, c.User)
|
||||
if err != nil {
|
||||
return ErrorToHTTP(err, false), err
|
||||
}
|
||||
}
|
||||
|
||||
var code int
|
||||
var err error
|
||||
|
||||
switch c.Router {
|
||||
case "download":
|
||||
code, err = downloadHandler(c, w, r)
|
||||
case "checksum":
|
||||
code, err = checksumHandler(c, w, r)
|
||||
case "command":
|
||||
code, err = command(c, w, r)
|
||||
case "search":
|
||||
code, err = search(c, w, r)
|
||||
case "resource":
|
||||
code, err = resourceHandler(c, w, r)
|
||||
case "users":
|
||||
code, err = usersHandler(c, w, r)
|
||||
case "settings":
|
||||
code, err = settingsHandler(c, w, r)
|
||||
case "share":
|
||||
code, err = shareHandler(c, w, r)
|
||||
default:
|
||||
code = http.StatusNotFound
|
||||
}
|
||||
|
||||
return code, err
|
||||
}
|
||||
|
||||
// serveChecksum calculates the hash of a file. Supports MD5, SHA1, SHA256 and SHA512.
|
||||
func checksumHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
query := r.URL.Query().Get("algo")
|
||||
|
||||
val, err := c.File.Checksum(query)
|
||||
if err == fm.ErrInvalidOption {
|
||||
return http.StatusBadRequest, err
|
||||
} else if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
w.Write([]byte(val))
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// splitURL splits the path and returns everything that stands
|
||||
// before the first slash and everything that goes after.
|
||||
func splitURL(path string) (string, string) {
|
||||
if path == "" {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
path = strings.TrimPrefix(path, "/")
|
||||
|
||||
i := strings.Index(path, "/")
|
||||
if i == -1 {
|
||||
return "", path
|
||||
}
|
||||
|
||||
return path[0:i], path[i:]
|
||||
}
|
||||
|
||||
// renderFile renders a file using a template with some needed variables.
|
||||
func renderFile(c *fm.Context, w http.ResponseWriter, file string) (int, error) {
|
||||
tpl := template.Must(template.New("file").Parse(c.Assets.MustString(file)))
|
||||
|
||||
var contentType string
|
||||
switch filepath.Ext(file) {
|
||||
case ".html":
|
||||
contentType = "text/html"
|
||||
case ".js":
|
||||
contentType = "application/javascript"
|
||||
case ".json":
|
||||
contentType = "application/json"
|
||||
default:
|
||||
contentType = "text"
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", contentType+"; charset=utf-8")
|
||||
|
||||
data := map[string]interface{}{
|
||||
"BaseURL": c.RootURL(),
|
||||
"NoAuth": c.NoAuth,
|
||||
"Version": fm.Version,
|
||||
"CSS": template.CSS(c.CSS),
|
||||
"ReCaptcha": c.ReCaptchaKey != "" && c.ReCaptchaSecret != "",
|
||||
"ReCaptchaKey": c.ReCaptchaKey,
|
||||
"ReCaptchaSecret": c.ReCaptchaSecret,
|
||||
}
|
||||
|
||||
if c.StaticGen != nil {
|
||||
data["StaticGen"] = c.StaticGen.Name()
|
||||
}
|
||||
|
||||
err := tpl.Execute(w, data)
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// sharePage build the share page.
|
||||
func sharePage(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
s, err := c.Store.Share.Get(r.URL.Path)
|
||||
if err == fm.ErrNotExist {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return renderFile(c, w, "static/share/404.html")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
if s.Expires && s.ExpireDate.Before(time.Now()) {
|
||||
c.Store.Share.Delete(s.Hash)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return renderFile(c, w, "static/share/404.html")
|
||||
}
|
||||
|
||||
r.URL.Path = s.Path
|
||||
|
||||
info, err := os.Stat(s.Path)
|
||||
if err != nil {
|
||||
c.Store.Share.Delete(s.Hash)
|
||||
return ErrorToHTTP(err, false), err
|
||||
}
|
||||
|
||||
c.File = &fm.File{
|
||||
Path: s.Path,
|
||||
Name: info.Name(),
|
||||
ModTime: info.ModTime(),
|
||||
Mode: info.Mode(),
|
||||
IsDir: info.IsDir(),
|
||||
Size: info.Size(),
|
||||
}
|
||||
|
||||
dl := r.URL.Query().Get("dl")
|
||||
|
||||
if dl == "" || dl == "0" {
|
||||
tpl := template.Must(template.New("file").Parse(c.Assets.MustString("static/share/index.html")))
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
err := tpl.Execute(w, map[string]interface{}{
|
||||
"BaseURL": c.RootURL(),
|
||||
"File": c.File,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return downloadHandler(c, w, r)
|
||||
}
|
||||
|
||||
// renderJSON prints the JSON version of data to the browser.
|
||||
func renderJSON(w http.ResponseWriter, data interface{}) (int, error) {
|
||||
marsh, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if _, err := w.Write(marsh); err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// matchURL checks if the first URL matches the second.
|
||||
func matchURL(first, second string) bool {
|
||||
first = strings.ToLower(first)
|
||||
second = strings.ToLower(second)
|
||||
|
||||
return strings.HasPrefix(first, second)
|
||||
}
|
||||
|
||||
// ErrorToHTTP converts errors to HTTP Status Code.
|
||||
func ErrorToHTTP(err error, gone bool) int {
|
||||
switch {
|
||||
case err == nil:
|
||||
return http.StatusOK
|
||||
case os.IsPermission(err):
|
||||
return http.StatusForbidden
|
||||
case os.IsNotExist(err):
|
||||
if !gone {
|
||||
return http.StatusNotFound
|
||||
}
|
||||
|
||||
return http.StatusGone
|
||||
case os.IsExist(err):
|
||||
return http.StatusConflict
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue