14 const PARAM_IDS = "ids"
17 // ============================================================================
18 func bookMimeType(bookPath string) string {
19 upper := strings.ToUpper(bookPath)
21 if strings.HasSuffix(upper, ".EPUB") {
22 return "application/epub+zip"
23 } else if strings.HasSuffix(upper, ".PDF") {
24 return "application/pdf"
26 fmt.Println("Warning: Cannot determine MIME type, will use application/octet-stream:", bookPath)
27 return "application/octet-stream"
31 func efsPathForId(efsId int) string {
34 idStr := fmt.Sprintf("%010d", efsId)
35 path := fmt.Sprintf("%s/efs/%s/%s/%s/%s/%s.dat", config.basePath, idStr[0:2], idStr[2:4], idStr[4:6], idStr[6:8], idStr)
40 func handler(w http.ResponseWriter, r *http.Request) {
43 handleError(w, err.Error())
47 action := strings.Split(r.URL.Path[1:], "/")[0]
62 "Unrecognized request: %s\nid: %s\nURL: %s\nQuery: %s\n",
70 // Download a book, based on the path stored in the DB
71 func handleBook(w http.ResponseWriter, r *http.Request) {
72 fmt.Println("handleBook:", r.URL.Path)
73 path := r.URL.Path[1:]
74 tok := strings.Split(path, "/")
76 handleError(w, fmt.Sprintf("Unexpected path for book download: %s\n", path))
80 bookId, err := strconv.Atoi(tok[1])
81 if (nil != err) || (0 == bookId) {
82 msg := fmt.Sprintf("Invalid id for book download: \"%s\" (%s)\n", path, err.Error())
87 bookPath := queryBookPathById(bookId)
88 if 0 == len(bookPath) {
89 handleError(w, fmt.Sprintf("No book for ID: %s\n", bookId))
93 bookFileName := filepath.Base(bookPath)
95 mimeType := bookMimeType(bookPath)
96 if 0 == len(mimeType) {
97 handleError(w, fmt.Sprintf("Failed to determine MIME type for book: %s\n", bookPath))
102 info, err = os.Stat(bookPath)
104 handleError(w, fmt.Sprintf("Failed to read file metadata: \"%s\" (%s)\n", bookPath, err.Error()))
107 modTime := info.ModTime()
110 fd, err = os.Open(bookPath)
112 handleError(w, fmt.Sprintf("Failed to open file: \"%s\" (%s)\n", bookPath, err.Error()))
117 // TODO: handle non-ASCII file names. Need to look up the permutations on how to encode that.
118 w.Header().Set("Content-Disposition", "attachment; filename=" + bookFileName)
119 w.Header().Set("Content-Type", mimeType)
120 http.ServeContent(w, r, bookFileName, modTime, fd)
123 func handleDownload(w http.ResponseWriter, r *http.Request) {
124 path := r.URL.Path[1:]
125 tok := strings.Split(path, "/")
127 fmt.Fprintln(w, "Unexpected path for download:", path)
130 efsId, err := strconv.Atoi(tok[1])
131 if (nil != err) || (0 == efsId) {
132 fmt.Fprintln(w, "Invalid id for download:", path, err)
136 mimeType := queryMimeTypeByEfsId(efsId)
137 if 0 == len(mimeType) {
138 fmt.Fprintln(w, "No MIME type found for id:", efsId)
142 efsPath := efsPathForId(efsId)
145 fd, err = os.Open(efsPath)
147 fmt.Fprintln(w, "Failed to read file for id:", efsId, err)
152 w.Header().Set("Content-Type", mimeType)
156 func handleError(w http.ResponseWriter, msg string) {
157 fmt.Printf("ERROR: %s", msg)
158 http.Error(w, msg, http.StatusInternalServerError)
161 func handleInfo(w http.ResponseWriter, r *http.Request) {
162 idParams := r.Form[PARAM_IDS]
163 if 1 != len(idParams) {
164 handleError(w, "ERROR! Detected either zero or multiple ids= parameters. Exactly one expected.")
168 idParam := idParams[0]
169 idStrings := strings.Split(idParam, ",")
170 ids := make([]int, len(idStrings))
172 for i, v := range(idStrings) {
173 ids[i], err = strconv.Atoi(v)
179 books := queryBooksByIds(ids)
182 jsonValue, err = json.Marshal(books)
184 handleError(w, err.Error())
190 func handleSearch(w http.ResponseWriter, r *http.Request) {
193 fields := []Field{Author, Language, List, Series, Sort, Title}
195 terms := make([]SearchTerm, len(fields))
198 for _, fv := range(fields) {
199 paramName := fv.String()
200 paramValues := r.Form[paramName]
201 for _, pv := range(paramValues) {
202 if count >= len(terms) {
203 fmt.Printf("WARNING: limit of %d search terms exceeded. One or more terms ignored.", len(terms))
206 terms[count] = SearchTerm{Attribute:fv, Text:pv}
211 terms = terms[:count]
213 ids := queryIds(terms)
215 jsonValue, err := json.Marshal(ids)
217 handleError(w, err.Error())