Пример #1
0
func handleImageDetails(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	db := sq.DB(ctx)
	img, err := ImageByID(db, web.Args(ctx).ByIndex(0))
	switch err {
	case nil:
		// all good
	case sq.ErrNotFound:
		web.StdHTMLResp(w, http.StatusNotFound)
		return
	default:
		log.Error("cannot get image",
			"image", web.Args(ctx).ByIndex(0),
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	img.Tags, err = ImageTags(db, img.ImageID)
	if err != nil {
		log.Error("cannot get image",
			"image", web.Args(ctx).ByIndex(0),
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	web.JSONResp(w, img, http.StatusOK)
}
Пример #2
0
func handleListImages(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	offset, _ := strconv.ParseInt(r.URL.Query().Get("offset"), 10, 64)
	opts := ImagesOpts{
		Offset: offset,
		Limit:  200,
	}

	// narrow to images tagged as specified
	for name, values := range r.URL.Query() {
		if !strings.HasPrefix(name, "tag_") {
			continue
		}
		for _, value := range values {
			opts.Tags = append(opts.Tags, KeyValue{
				Key:   name[4:],
				Value: value,
			})
		}
	}

	imgs, err := Images(sq.DB(ctx), opts)
	if err != nil {
		log.Error("cannot list images", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}
	if imgs == nil {
		imgs = make([]*Image, 0)
	}

	resp := struct {
		Images []*Image `json:"images"`
	}{
		Images: imgs,
	}
	web.JSONResp(w, resp, http.StatusOK)
}
Пример #3
0
func handleUploadImage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	if err := r.ParseMultipartForm(10 * megabyte); err != nil {
		web.JSONResp(w, err.Error(), http.StatusBadRequest)
		return
	}

	var header *multipart.FileHeader
	for _, headers := range r.MultipartForm.File {
		for _, h := range headers {
			log.Debug("uploading file", "name", h.Filename)
			if header != nil {
				web.JSONErr(w, "cannot upload more than one time at once", http.StatusBadRequest)
				return
			}
			header = h
		}
	}
	if header == nil {
		web.JSONErr(w, "image file missing", http.StatusBadRequest)
		return
	}
	if !strings.HasSuffix(strings.ToLower(header.Filename), ".jpg") {
		// XXX this is not the best validation
		web.JSONErr(w, "only JPEG format is allowed", http.StatusBadRequest)
		return
	}

	fd, err := header.Open()
	if err != nil {
		log.Error("cannot open uploaded file",
			"name", header.Filename,
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}
	defer fd.Close()

	image, err := imageMeta(fd)
	if err != nil {
		log.Error("cannot extract image metadata", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	// store image in database
	db := sq.DB(ctx)
	image, err = CreateImage(db, *image)
	switch err {
	case nil:
		// all good
	case sq.ErrConflict:
		// image already exists, nothing more to do here
		web.JSONResp(w, image, http.StatusOK)
		return
	default:
		log.Error("cannot create object", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	if _, err := fd.Seek(0, os.SEEK_SET); err != nil {
		log.Error("cannot seek image", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	fs := FileStore(ctx)
	if err := fs.Put(image, fd); err != nil {
		log.Error("cannot store image", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}
	log.Debug("image file created", "id", image.ImageID)

	web.JSONResp(w, image, http.StatusCreated)
}
Пример #4
0
func handleServeImage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	img, err := ImageByID(sq.DB(ctx), web.Args(ctx).ByIndex(0))
	switch err {
	case nil:
		// all good
	case sq.ErrNotFound:
		web.StdJSONResp(w, http.StatusNotFound)
		return
	default:
		log.Error("cannot get object",
			"object", web.Args(ctx).ByIndex(0),
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	if web.CheckLastModified(w, r, img.Created) {
		return
	}

	fs := FileStore(ctx)
	fd, err := fs.Read(img.Created.Year(), img.ImageID)
	if err != nil {
		log.Error("cannot read image file",
			"image", img.ImageID,
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}
	defer fd.Close()

	w.Header().Set("X-Image-ID", img.ImageID)
	w.Header().Set("X-Image-Width", fmt.Sprint(img.Width))
	w.Header().Set("X-Image-Height", fmt.Sprint(img.Height))
	w.Header().Set("X-Image-Created", img.Created.Format(time.RFC3339))
	w.Header().Set("Content-Type", "image/jpeg")

	if r.URL.Query().Get("resize") == "" {
		io.Copy(w, fd)
		return
	}

	image, err := jpeg.Decode(fd)
	if err != nil {
		log.Error("cannot read image file",
			"image", img.ImageID,
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}
	var width, height int
	if _, err := fmt.Sscanf(r.URL.Query().Get("resize"), "%dx%d", &width, &height); err != nil {
		log.Error("cannot resize image",
			"image", img.ImageID,
			"error", err.Error())
	} else {
		switch img.Orientation {
		case 1:
			// all good
		case 3:
			image = imaging.Rotate180(image)
		case 8:
			image = imaging.Rotate90(image)
		case 6:
			image = imaging.Rotate270(image)
		default:
			log.Debug("unknown image orientation",
				"decoder", "EXIF",
				"image", img.ImageID,
				"value", fmt.Sprint(img.Orientation))
		}
		image = imaging.Fill(image, width, height, imaging.Center, imaging.Linear)
	}
	imaging.Encode(w, image, imaging.JPEG)
}
Пример #5
0
func handleTagImage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	var input struct {
		Name  string
		Value string
	}
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		web.JSONErr(w, err.Error(), http.StatusBadRequest)
		return
	}

	var errs []string
	if input.Name == "" {
		errs = append(errs, `"name" is required`)
	}
	if input.Value == "" {
		errs = append(errs, `"value" is required`)
	}
	if len(errs) != 0 {
		web.JSONErrs(w, errs, http.StatusBadRequest)
		return
	}

	db := sq.DB(ctx)

	img, err := ImageByID(db, web.Args(ctx).ByIndex(0))
	switch err {
	case nil:
		// all good
	case sq.ErrNotFound:
		web.JSONErr(w, "parent image does not exist", http.StatusBadRequest)
		return
	default:
		log.Error("database error",
			"image", web.Args(ctx).ByIndex(0),
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	tag, err := CreateTag(db, Tag{
		ImageID: img.ImageID,
		Name:    input.Name,
		Value:   input.Value,
	})
	switch err {
	case nil:
		// all good, update storage meta
	case sq.ErrConflict:
		web.JSONResp(w, tag, http.StatusOK)
		return
	default:
		log.Error("cannot create object", "error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	if img.Tags, err = ImageTags(db, img.ImageID); err != nil {
		log.Error("cannot get image tags",
			"image", img.ImageID,
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	fs := FileStore(ctx)
	if err := fs.PutMeta(img); err != nil {
		log.Error("cannot store image metadata",
			"image", img.ImageID,
			"error", err.Error())
		web.StdJSONResp(w, http.StatusInternalServerError)
		return
	}

	web.JSONResp(w, tag, http.StatusCreated)
}