X-Git-Url: http://jaekl.net/gitweb/?p=quanweb.git;a=blobdiff_plain;f=main%2Fhandler.go;h=2d8076e35720c20e5422ecd87fe9eca83f70c7c9;hp=255f19397a6fd6db357bae249a3d882f360e32f7;hb=2df0b2d1b40d59b36cb0964f1bbfb5247b55178a;hpb=bb350871a3ae81484ae3a736b16018e340908251 diff --git a/main/handler.go b/main/handler.go index 255f193..2d8076e 100644 --- a/main/handler.go +++ b/main/handler.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "os" + "path/filepath" "strconv" "strings" ) @@ -14,6 +15,19 @@ const PARAM_IDS = "ids" const MAX_TERMS = 10 // ============================================================================ +func bookMimeType(bookPath string) string { + upper := strings.ToUpper(bookPath) + + if strings.HasSuffix(upper, ".EPUB") { + return "application/epub+zip" + } else if strings.HasSuffix(upper, ".PDF") { + return "application/pdf" + } else { + fmt.Println("Warning: Cannot determine MIME type, will use application/octet-stream:", bookPath) + return "application/octet-stream" + } +} + func efsPathForId(efsId int) string { config := getConfig() @@ -33,6 +47,8 @@ func handler(w http.ResponseWriter, r *http.Request) { action := strings.Split(r.URL.Path[1:], "/")[0] switch(action) { + case "book": + handleBook(w, r) case "download": handleDownload(w, r) case "info": @@ -48,6 +64,57 @@ func handler(w http.ResponseWriter, r *http.Request) { } } +// Download a book, based on the path stored in the DB +func handleBook(w http.ResponseWriter, r *http.Request) { + path := r.URL.Path[1:] + tok := strings.Split(path, "/") + if 2 != len(tok) { + fmt.Fprintln(w, "Unexpected path for book download:", path) + return + } + + bookId, err := strconv.Atoi(tok[1]) + if (nil != err) || (0 == bookId) { + fmt.Fprintln(w, "Invalid id for book download:", path, err) + return + } + + bookPath := queryBookPathById(bookId) + if 0 == len(bookPath) { + fmt.Fprintln(w, "No book for ID:", bookId) + return + } + + bookFileName := filepath.Base(bookPath) + + mimeType := bookMimeType(bookPath) + if 0 == len(mimeType) { + fmt.Fprintln(w, "Failed to determine MIME type for book:", bookPath) + return + } + + var info os.FileInfo + info, err = os.Stat(bookPath) + if nil != err { + fmt.Fprintln(w, "Failed to read file metadata:", bookPath, err) + return + } + modTime := info.ModTime() + + var fd *os.File + fd, err = os.Open(bookPath) + if nil != err { + fmt.Fprintln(w, "Failed to open file:", bookPath, err) + return + } + defer fd.Close() + + // TODO: handle non-ASCII file names. Need to look up the permutations on how to encode that. + w.Header().Set("Content-Disposition", "attachment; filename=" + bookFileName) + w.Header().Set("Content-Type", mimeType) + http.ServeContent(w, r, bookFileName, modTime, fd) +} + func handleDownload(w http.ResponseWriter, r *http.Request) { path := r.URL.Path[1:] tok := strings.Split(path, "/") @@ -77,6 +144,7 @@ func handleDownload(w http.ResponseWriter, r *http.Request) { } defer fd.Close() + w.Header().Set("Content-Type", mimeType) io.Copy(w, fd) } @@ -90,8 +158,8 @@ func handleInfo(w http.ResponseWriter, r *http.Request) { idParam := idParams[0] idStrings := strings.Split(idParam, ",") ids := make([]int, len(idStrings)) + var err error for i, v := range(idStrings) { - var err error ids[i], err = strconv.Atoi(v) if nil != err { ids[i] = 0 @@ -101,7 +169,6 @@ func handleInfo(w http.ResponseWriter, r *http.Request) { books := queryBooksByIds(ids) var jsonValue []byte - var err error jsonValue, err = json.Marshal(books) if nil != err { fmt.Fprintln(w, "ERROR!", err) @@ -111,6 +178,8 @@ func handleInfo(w http.ResponseWriter, r *http.Request) { } func handleSearch(w http.ResponseWriter, r *http.Request) { + var err error + fields := []Field{Author, Title, Series} terms := make([]SearchTerm, len(fields)) @@ -121,7 +190,7 @@ func handleSearch(w http.ResponseWriter, r *http.Request) { paramValues := r.Form[paramName] for _, pv := range(paramValues) { if count >= len(terms) { - fmt.Printf("WARNING: limit of %v search terms exceeded. One or more terms ignored.") + fmt.Printf("WARNING: limit of %d search terms exceeded. One or more terms ignored.", len(terms)) break } terms[count] = SearchTerm{Attribute:fv, Text:pv} @@ -140,3 +209,4 @@ func handleSearch(w http.ResponseWriter, r *http.Request) { w.Write(jsonValue) } } +