github.com/saadullahsaeed/fragmenta-cms@v1.5.4/src/app/handlers.go (about)

     1  package app
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"path"
     7  	"strings"
     8  
     9  	"github.com/fragmenta/server"
    10  	"github.com/fragmenta/server/config"
    11  	"github.com/fragmenta/server/log"
    12  	"github.com/fragmenta/view"
    13  )
    14  
    15  // Serve static files (assets, images etc)
    16  func fileHandler(w http.ResponseWriter, r *http.Request) error {
    17  
    18  	// First try serving assets
    19  	err := serveAsset(w, r)
    20  	if err == nil {
    21  		return nil
    22  	}
    23  
    24  	// If assets fail, try to serve file in public
    25  	return serveFile(w, r)
    26  }
    27  
    28  // serveFile serves a file from ./public if it exists
    29  func serveFile(w http.ResponseWriter, r *http.Request) error {
    30  
    31  	// Try a local path in the public directory
    32  	localPath := "./public" + path.Clean(r.URL.Path)
    33  	s, err := os.Stat(localPath)
    34  	if err != nil {
    35  		// If file not found return 404
    36  		if os.IsNotExist(err) {
    37  			return server.NotFoundError(err)
    38  		}
    39  
    40  		// For other errors return not authorised
    41  		return server.NotAuthorizedError(err)
    42  	}
    43  
    44  	// If not a file return immediately
    45  	if s.IsDir() {
    46  		return nil
    47  	}
    48  
    49  	// If the file exists and we can access it, serve it with cache control
    50  	w.Header().Set("Cache-Control", "max-age:3456000, public")
    51  	http.ServeFile(w, r, localPath)
    52  	return nil
    53  }
    54  
    55  // serveAsset serves a file from ./public/assets usings appAssets
    56  func serveAsset(w http.ResponseWriter, r *http.Request) error {
    57  
    58  	p := path.Clean(r.URL.Path)
    59  
    60  	// It must be under /assets, or we don't serve
    61  	if !strings.HasPrefix(p, "/assets/") {
    62  		return server.NotFoundError(nil)
    63  	}
    64  
    65  	// Try to find an asset in our list
    66  	f := appAssets.File(path.Base(p))
    67  	if f == nil {
    68  		return server.NotFoundError(nil)
    69  	}
    70  
    71  	// Serve the local file, with cache control
    72  	localPath := "./" + f.LocalPath()
    73  	w.Header().Set("Cache-Control", "max-age:3456000, public")
    74  	http.ServeFile(w, r, localPath)
    75  	return nil
    76  }
    77  
    78  // errHandler renders an error using error templates if available
    79  func errHandler(w http.ResponseWriter, r *http.Request, e error) {
    80  
    81  	// Cast the error to a status error if it is one, if not wrap it in a Status 500 error
    82  	err := server.ToStatusError(e)
    83  	log.Error(log.V{"error": err})
    84  
    85  	view := view.NewWithPath("", w)
    86  	view.AddKey("title", err.Title)
    87  	view.AddKey("message", err.Message)
    88  	// In production, provide no detail for security reasons
    89  	if !config.Production() {
    90  		view.AddKey("status", err.Status)
    91  		view.AddKey("file", err.FileLine())
    92  		view.AddKey("error", err.Err)
    93  	}
    94  	view.Template("app/views/error.html.got")
    95  	w.WriteHeader(err.Status)
    96  	view.Render()
    97  }