// vi:ts=4:sts=4:sw=4:noet:tw=72 package main import ( "flag" "fmt" "log" "net/http" "strconv" "strings" "github.com/davidbyttow/govips/pkg/vips" ) var ( imgServer = flag.String("s", "https://images.example.com/", "URL prefix") listenAddr = flag.Int("l", "0.0.0.0:8080", "Listen address") ) func init() { flag.Parse() } func main() { // Start vips with the default configuration vips.Startup(nil) defer vips.Shutdown() http.HandleFunc("/", resizeHandler) log.Fatal(http.ListenAndServe(listenAddr, nil)) } func resizeHandler(w http.ResponseWriter, r *http.Request) { // Get the query parameters from the request URL path := r.URL.EscapedPath() parm := strings.Split(path, "/") if len(parm) < 3 { w.Write([]byte(fmt.Sprintf("url, width and height are required"))) w.WriteHeader(http.StatusBadRequest) return } queryUrl := parm[2] size := strings.Split(parm[1], "x") if len(size) < 2 { w.Write([]byte(fmt.Sprintf("url, width and height are required"))) w.WriteHeader(http.StatusBadRequest) return } queryWidth := size[0] queryHeight := size[1] // Validate that all three required fields are present if queryUrl == "" || queryWidth == "" || queryHeight == "" { w.Write([]byte(fmt.Sprintf("url, width and height are required"))) w.WriteHeader(http.StatusBadRequest) return } // Convert width and height to integers width, errW := strconv.Atoi(queryWidth) height, errH := strconv.Atoi(queryHeight) if errW != nil || errH != nil { w.Write([]byte(fmt.Sprintf("width and height must be integers"))) w.WriteHeader(http.StatusBadRequest) return } // Start fetching the image from the given url resp, err := http.Get(imgServer + queryUrl) if err != nil { w.Write([]byte(fmt.Sprintf("failed to get %s: %v", queryUrl, err))) w.WriteHeader(http.StatusBadRequest) return } // Ensure that a valid response was given if resp.StatusCode/100 != 2 { w.Write([]byte(fmt.Sprintf("failed to get %s: status %d", queryUrl, resp.StatusCode))) w.WriteHeader(http.StatusBadRequest) return } defer resp.Body.Close() // govips returns the output of the image as a []byte object. We don't need // it since we are directly piping it to the ResponseWriter _, _, err = vips.NewTransform(). Load(resp.Body). ResizeStrategy(vips.ResizeStrategyStretch). Resize(width, height). Output(w). Apply() if err != nil { w.Write([]byte(fmt.Sprintf("failed to resize %s: %v", queryUrl, err))) w.WriteHeader(http.StatusInternalServerError) return } }