func GetImageInfo(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	url := r.URL.Query().Get("url")
	if url == "" {
		respond.ApiError(w, 422, errors.New("no image url"))
		return
	}
	response, err := app.Fetcher.Get(ctx, url)
	if err != nil {
		respond.ApiError(w, 422, err)
		return
	}
	data := response.Data
	ng := imagick.Engine{}
	imfo, err := ng.GetImageInfo(data)
	if err != nil {
		respond.ApiError(w, 422, err)
		return
	}
	imfo.URL = response.URL.String()
	imfo.Mimetype = MimeTypes[imfo.Format]
	w.Header().Set("X-Meta-Width", fmt.Sprintf("%d", imfo.Width))
	w.Header().Set("X-Meta-Height", fmt.Sprintf("%d", imfo.Height))
	w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", app.Config.CacheMaxAge))
	respond.JSON(w, 200, imfo)
}
TODO: this can be optimized significantly..........
Ping / DecodeConfig ... do we have to use image magick.......?
package server
import (
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
	"github.com/goware/lg"
	"github.com/goware/urlx"
	"github.com/pressly/chi"
	"github.com/pressly/imgry"
	"github.com/pressly/imgry/imagick"
)
var (
	MimeTypes = map[string]string{
		"png":  "image/png",
		"jpeg": "image/jpeg",
		"jpg":  "image/jpeg",
		"bmp":  "image/bmp",
		"bm":   "image/bmp",
		"gif":  "image/gif",
		"ico":  "image/x-icon",
	}
	ErrInvalidURL = errors.New("invalid url")
)
func BucketGetIndex(w http.ResponseWriter, r *http.Request) {
	if r.URL.Query().Get("url") == "" {
		respond.Data(w, 200, []byte{})
		return
	}
	BucketFetchItem(w, r)
}
func BucketFetchItem(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	bucket, err := NewBucket(chi.URLParamFromCtx(ctx, "bucket"))
	if err != nil {
		respond.ImageError(w, 422, err)
		return
	}
	fetchUrl := r.URL.Query().Get("url")
	if fetchUrl == "" {
		respond.ImageError(w, 422, ErrInvalidURL)
		return
	}
	u, err := urlx.Parse(fetchUrl)
	if err != nil {
		respond.ImageError(w, 422, ErrInvalidURL)
		return
	}
	fetchUrl = u.String()
	imKey := sha1Hash(fetchUrl)  
	rctx := chi.RouteContext(ctx)
	rctx.URLParams.Set("key", imKey)
	_, err = bucket.DbFindImage(ctx, imKey, nil)
	if err != nil && err != ErrImageNotFound {
		respond.ImageError(w, 422, err)
		return
	}
	if err == ErrImageNotFound {
		_, err := bucket.AddImagesFromUrls(ctx, []string{fetchUrl})
		if err != nil {
			lg.Errorf("Fetching failed for %s because %s", fetchUrl, err)
			respond.ImageError(w, 422, err)
			return
		}
	}
	BucketGetItem(w, r)
}
func BucketGetItem(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	bucket, err := NewBucket(chi.URLParamFromCtx(ctx, "bucket"))
	if err != nil {
		lg.Errorf("Failed to create bucket for %s cause: %s", r.URL, err)
		respond.ImageError(w, 422, err)
		return
	}
	sizing, err := imgry.NewSizingFromQuery(r.URL.RawQuery)
	if err != nil {
		lg.Errorf("Failed to create sizing for %s cause: %s", r.URL, err)
		respond.ImageError(w, 422, err)
		return
	}
	im, err := bucket.GetImageSize(ctx, chi.URLParamFromCtx(ctx, "key"), sizing)
	if err != nil {
		lg.Errorf("Failed to get image for %s cause: %s", r.URL, err)
		respond.ImageError(w, 422, err)
		return
	}
	w.Header().Set("Content-Type", im.MimeType())
	w.Header().Set("X-Meta-Width", fmt.Sprintf("%d", im.Width))
	w.Header().Set("X-Meta-Height", fmt.Sprintf("%d", im.Height))
	w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", app.Config.CacheMaxAge))
	w.Header().Set("Last-Modified", time.Now().Format(http.TimeFormat))
	if r.URL.Query().Get("info") != "" {
		respond.JSON(w, http.StatusOK, im)
		return
	}
	respond.Data(w, 200, im.Data)
}