Skip to content

Instantly share code, notes, and snippets.

@mynameisfiber
Created May 3, 2012 15:30
Show Gist options
  • Save mynameisfiber/2586507 to your computer and use it in GitHub Desktop.
Save mynameisfiber/2586507 to your computer and use it in GitHub Desktop.
imggtr.go
package main
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"path"
"strings"
)
func rev(in []byte) []byte {
msize := len(in) - 1
out := make([]byte, len(in))
for i := msize; i >= 0; i-- {
out[msize-i] = in[i]
}
return out
}
func bytesToInt(in []byte) int {
value := 0
for _, b := range in {
value = (value << 8) | (int(b) & 0xFF)
}
return value
}
func extractSizePNG(body_fd io.Reader) (width, height int, err error) {
// Offsets from PNG v1.2 specs. See:
// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
body := make([]byte, 24)
io.ReadFull(body_fd, body)
if bytes.Equal(body[1:4], []byte{80, 78, 71}) == false {
return 0, 0, errors.New("Not a valid PNG")
}
return bytesToInt(body[16:20]), bytesToInt(body[20:24]), nil
}
func extractSizeGIF(body_fd io.Reader) (width, height int, err error) {
// http://www.onicos.com/staff/iz/formats/gif.html
body := make([]byte, 10)
io.ReadFull(body_fd, body)
if bytes.Equal(body[:3], []byte{71, 73, 70}) == false {
return 0, 0, errors.New("Not a valid GIF")
}
return bytesToInt(rev(body[6:8])), bytesToInt(rev(body[8:10])), nil
}
func extractSizeJPEG(body_fd io.Reader) (width, height int, err error) {
// http://www.onicos.com/staff/iz/formats/jpeg.html
header := make([]byte, 10)
io.ReadFull(body_fd, header)
if bytes.Equal(header[6:10], []byte{74, 70, 73, 70}) == false {
return 0, 0, errors.New("Not a valid JPEG")
}
b := make([]byte, 2)
for bytes.Equal(b, []byte{255, 192}) == false {
io.ReadFull(body_fd, b)
}
c0header := make([]byte, 8)
io.ReadFull(body_fd, c0header)
fmt.Println(c0header)
return bytesToInt(c0header[5:7]), bytesToInt(c0header[3:5]), nil
}
func extractSize(ext string, body_fd io.Reader) (width, height int, err error) {
if ext == ".png" {
return extractSizePNG(body_fd)
} else if ext == ".gif" {
return extractSizeGIF(body_fd)
} else if ext == ".jpg" || ext == ".jpeg" || ext == ".jpe" {
return extractSizeJPEG(body_fd)
} else {
return 0, 0, errors.New("Unknown filetype")
}
return
}
func FetchImage(imgUrlRaw string, w http.ResponseWriter) {
imgUrl, err := url.Parse(imgUrlRaw)
if err != nil {
fmt.Fprintf(w, "Malformed image URL: %s", err)
return
}
resp, err := http.Get(imgUrlRaw)
if err != nil {
fmt.Fprintf(w, "%s", err)
return
}
defer resp.Body.Close()
ext := strings.ToLower(path.Ext(imgUrl.Path))
width, height, err := extractSize(ext, resp.Body)
if err != nil {
fmt.Fprintf(w, "Could not extract resolution: %s", err)
return
}
fmt.Fprintf(w, "%d x %d\n", width, height)
}
func GetHandler(w http.ResponseWriter, r *http.Request) {
reqParams, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
fmt.Fprintf(w, "Error decoding request URI: %s", r.URL.RawQuery)
return
}
reqUrl := reqParams.Get("url")
if reqUrl == "" {
fmt.Fprintf(w, "Missing required parameter 'url'")
return
}
FetchImage(reqUrl, w)
}
func PingHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "OK")
}
func main() {
http.HandleFunc("/get", GetHandler)
http.HandleFunc("/ping", PingHandler)
http.HandleFunc("/", PingHandler)
http.ListenAndServe(":8080", nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment