resize
This commit is contained in:
		
							parent
							
								
									271590f775
								
							
						
					
					
						commit
						34817456b1
					
				
					 2 changed files with 79 additions and 76 deletions
				
			
		
							
								
								
									
										11
									
								
								Dockerfile
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								Dockerfile
									
										
									
									
									
								
							| 
						 | 
					@ -1,21 +1,14 @@
 | 
				
			||||||
FROM golang:latest
 | 
					FROM golang:latest
 | 
				
			||||||
 | 
					 | 
				
			||||||
MAINTAINER Andreas Neue <an@dnix.de>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN apt -y update && \
 | 
					RUN apt -y update && \
 | 
				
			||||||
    apt -y upgrade && \
 | 
					    apt -y upgrade && \
 | 
				
			||||||
    apt -y install libglib2.0-dev libexpat1-dev libjpeg-dev libpng-dev libgif-dev
 | 
					    apt -y install libglib2.0-dev libexpat1-dev libjpeg-dev libpng-dev libgif-dev
 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /go/src/image-resizer
 | 
					WORKDIR /go/src/image-resizer
 | 
				
			||||||
COPY . .
 | 
					COPY . .
 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN wget https://github.com/libvips/libvips/releases/download/v8.7.3/vips-8.7.3.tar.gz && \
 | 
					RUN wget https://github.com/libvips/libvips/releases/download/v8.7.3/vips-8.7.3.tar.gz && \
 | 
				
			||||||
    tar xvzf vips-8.7.3.tar.gz && \
 | 
					    tar xvzf vips-8.7.3.tar.gz && \
 | 
				
			||||||
    cd vips-8.7.3 && \
 | 
					    cd vips-8.7.3 && \
 | 
				
			||||||
    ./configure && \
 | 
					    ./configure && \
 | 
				
			||||||
    make && \
 | 
					    make && \
 | 
				
			||||||
    make install && \
 | 
					    make install && \
 | 
				
			||||||
    go get -v -u github.com/davidbyttow/govips/pkg/vips && \
 | 
					    ldconfig
 | 
				
			||||||
    go install -v ./...
 | 
					RUN go get -v -u github.com/davidbyttow/govips/pkg/vips && go install -v ./...
 | 
				
			||||||
 | 
					 | 
				
			||||||
CMD ["image-resizer", "-s", "https://images.example.com/"]
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										144
									
								
								main.go
									
										
									
									
									
								
							
							
						
						
									
										144
									
								
								main.go
									
										
									
									
									
								
							| 
						 | 
					@ -22,6 +22,83 @@ func init() {
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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) < 4 {
 | 
				
			||||||
 | 
							writeError(w, "", "", "error in arguments", http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						method := parm[1]
 | 
				
			||||||
 | 
						args := parm[2]
 | 
				
			||||||
 | 
						imgPath := strings.Join(parm[3:], "/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Start fetching the image from the given url
 | 
				
			||||||
 | 
						resp, err := http.Get(*imgServer + imgPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							writeError(w, imgPath, method, "failed to fetch image", http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer resp.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch method {
 | 
				
			||||||
 | 
						case "resize":
 | 
				
			||||||
 | 
							size := strings.Split(args, "x")
 | 
				
			||||||
 | 
							if len(size) < 2 {
 | 
				
			||||||
 | 
								writeError(w, imgPath, method, "url, width, and height are required", http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							width := size[0]
 | 
				
			||||||
 | 
							height := size[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Validate that all three required fields are present
 | 
				
			||||||
 | 
							if imgPath == "" || width == "" || height == "" {
 | 
				
			||||||
 | 
								writeError(w, imgPath, method, "url, width, and height are required", http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Convert width and height to integers
 | 
				
			||||||
 | 
							iw, errW := strconv.Atoi(width)
 | 
				
			||||||
 | 
							ih, errH := strconv.Atoi(height)
 | 
				
			||||||
 | 
							if errW != nil || errH != nil {
 | 
				
			||||||
 | 
								writeError(w, imgPath, method, "width and height must be integers", http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Ensure that a valid response was given
 | 
				
			||||||
 | 
							if resp.StatusCode/100 != 2 {
 | 
				
			||||||
 | 
								writeError(w, imgPath, method, fmt.Sprintf("failed to fetch image (%v)", resp.StatusCode), http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 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.ResizeStrategyEmbed).
 | 
				
			||||||
 | 
								Resize(iw, ih).
 | 
				
			||||||
 | 
								Output(w).
 | 
				
			||||||
 | 
								Apply()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								writeError(w, imgPath, method, "failed to resize", http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							writeError(w, imgPath, method, "unknown method", http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeError(w http.ResponseWriter, imgPath, method, err string, status int) {
 | 
				
			||||||
 | 
						w.WriteHeader(status)
 | 
				
			||||||
 | 
						w.Write([]byte(fmt.Sprintf("Error [%s %s]: %s", method, imgPath, err)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	// Start vips with the default configuration
 | 
						// Start vips with the default configuration
 | 
				
			||||||
	vips.Startup(nil)
 | 
						vips.Startup(nil)
 | 
				
			||||||
| 
						 | 
					@ -30,70 +107,3 @@ func main() {
 | 
				
			||||||
	http.HandleFunc("/", resizeHandler)
 | 
						http.HandleFunc("/", resizeHandler)
 | 
				
			||||||
	log.Fatal(http.ListenAndServe(*listenAddr, nil))
 | 
						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
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue