Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading image from HTTP request's body in Go

Tags:

http

go

I'm playing with Go (first time ever) and I want to build a tool to retrieve images from Internet and cut them (even resize) but I'm stuck on the first step.

package main

import (
  "fmt"
  "http"
)

var client = http.Client{}

func cutterHandler(res http.ResponseWriter, req *http.Request) {
  reqImg, err := client.Get("http://www.google.com/intl/en_com/images/srpr/logo3w.png")
  if err != nil {
    fmt.Fprintf(res, "Error %d", err)
    return
  }
  buffer := make([]byte, reqImg.ContentLength)
  reqImg.Body.Read(buffer)
  res.Header().Set("Content-Length", fmt.Sprint(reqImg.ContentLength)) /* value: 7007 */
  res.Header().Set("Content-Type", reqImg.Header.Get("Content-Type")) /* value: image/png */
  res.Write(buffer)
}

func main() {
  http.HandleFunc("/cut", cutterHandler)
  http.ListenAndServe(":8080", nil) /* TODO Configurable */
}

I'm able to request an image (let's use Google logo) and to get its kind and size.

Indeed, I'm just re-writing the image (look at this as a toy "proxy"), setting Content-Length and Content-Type and writing the byte slice back but I get it wrong somewhere. See how it looks the final image rendered on Chromium 12.0.742.112 (90304):

Grotesque result

Also I checked the downloaded file and it is a 7007 bytes PNG image. It should be working properly if we look at the request:

GET /cut HTTP/1.1
User-Agent: curl/7.22.0 (i486-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.23 libssh2/1.2.8 librtmp/2.3
Host: 127.0.0.1:8080
Accept: /

HTTP/1.1 200 OK
Content-Length: 7007
Content-Type: image/png
Date: Tue, 27 Dec 2011 19:51:53 GMT

[PNG data]

What do you think I'm doing wrong here?

Disclaimer: I'm scratching my own itch, so probably I'm using the wrong tool :) Anyway, I can implement it on Ruby but before I would like to give Go a try.

Update: still scratching itches but... I think this is going to be a good side-of-side project so I'm opening it https://github.com/imdario/go-lazor If it is not useful, at least somebody can find usefulness with the references used to develop it. They were for me.

like image 727
Dario Castañé Avatar asked Dec 02 '22 00:12

Dario Castañé


1 Answers

I think you went too fast to the serve things part.

Focus on the first step, downloading the image.

Here you have a little program that downloads that image to memory.
It works on my 2011-12-22 weekly version, for r60.3 you just need to gofix the imports.

package main

import (
    "log"
    "io/ioutil"
    "net/http"
)

const url = "http://www.google.com/intl/en_com/images/srpr/logo3w.png"

func main() {
    // Just a simple GET request to the image URL
    // We get back a *Response, and an error
    res, err := http.Get(url)

    if err != nil {
        log.Fatalf("http.Get -> %v", err)
    }

    // We read all the bytes of the image
    // Types: data []byte
    data, err = ioutil.ReadAll(res.Body)

    if err != nil {
        log.Fatalf("ioutil.ReadAll -> %v", err)
    }

    // You have to manually close the body, check docs
    // This is required if you want to use things like
    // Keep-Alive and other HTTP sorcery.
    res.Body.Close()

    // You can now save it to disk or whatever...
    ioutil.WriteFile("google_logo.png", data, 0666)

    log.Println("I saved your image buddy!")
}

Voilá!

This will get the image to memory inside data.
Once you have that, you can decode it, crop it and serve back to the browser.

Hope this helps.

like image 115
toqueteos Avatar answered Dec 16 '22 02:12

toqueteos