package main import ( "fmt" "io" "io/ioutil" "log" "net/http" "os" "path" "strconv" "strings" "github.com/julienschmidt/httprouter" ) var files map[string]map[int][]string var IMAGE_TYPES map[string]int func serveImage(w http.ResponseWriter, r *http.Request, p httprouter.Params) { log.Printf("GET %s", r.URL.Path) abort := func(code int, reason string) { http.Error(w, reason, code) log.Printf("GET failed: %d %s", code, reason) } file, ok := files[p.ByName("type")] if !ok { abort(400, "Invalid Type") return } simageType := p.ByName("image_type") id := p.ByName("id") localPath := path.Join("./", p.ByName("type"), simageType, id) if _, err := os.Stat(localPath); err == nil { log.Println("-> Serving from local file") f, err := os.Open(localPath) defer f.Close() if err != nil { abort(500, "Could not open File") return } w.WriteHeader(200) io.Copy(w, f) return } if idx := strings.Index(id, ".jpg"); idx != -1 { id = id[:idx] } numId, err := strconv.ParseInt(id, 10, 0) if err != nil { abort(400, "Invalid ID") return } imageType, ok := IMAGE_TYPES[simageType] if !ok { abort(400, "Invalid image type") return } images, ok := file[int(numId)] if !ok { abort(404, "Invalid Target") return } if imageType < 0 || int(imageType) >= len(images) { abort(400, "Invalid image type") return } log.Println("-> downloading from acd") res, err := http.Get(images[int(imageType)]) if err != nil { abort(500, err.Error()) return } data, err := ioutil.ReadAll(res.Body) if err != nil { abort(500, err.Error()) return } if err := ioutil.WriteFile(localPath, data, 0755); err != nil { abort(500, err.Error()) return } w.Write(data) } func loadList(name string) error { data, err := ioutil.ReadFile(fmt.Sprintf("%s.list", name)) if err != nil { return err } files[name] = make(map[int][]string) entries := strings.Split(string(data), "\n") for _, entry := range entries { if entry == "" { continue } data := strings.Split(entry, " ") id, err := strconv.ParseInt(data[0], 10, 0) if err != nil { return err } if e, ok := files[name][int(id)]; ok { files[name][int(id)] = append(e, data[1]) } else { files[name][int(id)] = []string{data[1]} } } return nil } func main() { IMAGE_TYPES = make(map[string]int) IMAGE_TYPES["full"] = 0 IMAGE_TYPES["thumb"] = 1 files = make(map[string]map[int][]string) if err := loadList("gril"); err != nil { log.Fatal(err) } if err := loadList("series"); err != nil { log.Fatal(err) } router := httprouter.New() router.GET("/:type/:image_type/:id", serveImage) log.Println("starting image-on-demand on localhost:8081") log.Fatal(http.ListenAndServe("localhost:8081", router)) }