Skip to content
This repository has been archived by the owner on Apr 7, 2022. It is now read-only.

Commit

Permalink
add guid generator to support for service to return image urls to client
Browse files Browse the repository at this point in the history
  • Loading branch information
zhushaoping committed Sep 23, 2016
1 parent 7915458 commit c346ae8
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 17 deletions.
79 changes: 79 additions & 0 deletions guid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"crypto/md5"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"os"
"sync/atomic"
"time"
)

// objectIdCounter is atomically incremented when generating a new ObjectId
// using NewObjectId() function. It's used as a counter part of an id.
var objectIdCounter uint32 = 0

// machineId stores machine id generated once and used in subsequent calls
// to NewObjectId function.
var machineId = readMachineId()

// ObjectId is a unique ID identifying a BSON value. It must be exactly 12 bytes
// long. MongoDB objects by default have such a property set in their "_id"
// property.
//
// http://www.mongodb.org/display/DOCS/Object+IDs
type ObjectId string

// readMachineId generates machine id and puts it into the machineId global
// variable. If this function fails to get the hostname, it will cause
// a runtime error.
func readMachineId() []byte {
var sum [3]byte
id := sum[:]
hostname, err1 := os.Hostname()
if err1 != nil {
_, err2 := io.ReadFull(rand.Reader, id)
if err2 != nil {
panic(fmt.Errorf("cannot get hostname: %v; %v", err1, err2))
}
return id
}
hw := md5.New()
hw.Write([]byte(hostname))
copy(id, hw.Sum(nil))
return id
}

// NewObjectId returns a new unique ObjectId.
// 4byte 时间,
// 3byte 机器ID
// 2byte pid
// 3byte 自增ID
func NewObjectId() ObjectId {
var b [12]byte
// Timestamp, 4 bytes, big endian
binary.BigEndian.PutUint32(b[:], uint32(time.Now().Unix()))
// Machine, first 3 bytes of md5(hostname)
b[4] = machineId[0]
b[5] = machineId[1]
b[6] = machineId[2]
// Pid, 2 bytes, specs don't specify endianness, but we use big endian.
pid := os.Getpid()
b[7] = byte(pid >> 8)
b[8] = byte(pid)
// Increment, 3 bytes, big endian
i := atomic.AddUint32(&objectIdCounter, 1)
b[9] = byte(i >> 16)
b[10] = byte(i >> 8)
b[11] = byte(i)
return ObjectId(b[:])
}

// Hex returns a hex representation of the ObjectId.
// 返回16进制对应的字符串
func (id ObjectId) Hex() string {
return hex.EncodeToString([]byte(id))
}
52 changes: 35 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,63 @@ import (
// "github.com/unrolled/render" // or "gopkg.in/unrolled/render.v1"
)

type ImageRender struct {
BinaryPath *string
}

//render image with wkhtmltoimage with url
func renderImage(req *http.Request, format string, binPath string) ([]byte, error) {
func (r *ImageRender) GetBytes(req *http.Request, format string) ([]byte, error) {
err := req.ParseForm()
if err != nil {
return nil, err
}
url := req.Form.Get("url")

var html string
if len(url) == 0 {
return nil, errors.New("url can't be null")
html = req.Form.Get("html")

if len(html) == 0 {
return nil, errors.New("url can't be null")
} else {
url = "-"
log.Println("render for: ", html)
}
} else {
html = ""
log.Println("render for: ", url)
}
log.Println("render for: ", url)
c := ImageOptions{BinaryPath: binPath,
Input: url, Format: format}

c := ImageOptions{BinaryPath: *r.BinaryPath,
Input: url, Html: html, Format: format}

return GenerateImage(&c)
}

//render image bytes to browser
func (r *ImageRender) RenderBytes(w http.ResponseWriter, req *http.Request, format string) {
out, err := r.GetBytes(req, format)
if err != nil {
w.Write([]byte(fmt.Sprint(err)))
return
}
w.Write(out)
}

func main() {
binPath := flag.String("path", "/usr/local/bin/wkhtmltoimage", "wkhtmltoimage bin path")
port := flag.String("web.port", "8080", "web server port")
flag.Parse()
render := ImageRender{}
render.BinaryPath = binPath
// r := render.New()
mux := http.NewServeMux()

mux.HandleFunc("/render.png", func(w http.ResponseWriter, req *http.Request) {
out, err := renderImage(req, "png", *binPath)
if err != nil {
w.Write([]byte(fmt.Sprint(err)))
return
}
w.Write(out)
render.RenderBytes(w, req, "png")
})
mux.HandleFunc("/render.jpg", func(w http.ResponseWriter, req *http.Request) {
out, err := renderImage(req, "jpg", *binPath)
if err != nil {
w.Write([]byte(fmt.Sprint(err)))
return
}
w.Write(out)
render.RenderBytes(w, req, "jpg")
})
if len(*port) == 0 {
*port = "8080"
Expand Down

0 comments on commit c346ae8

Please sign in to comment.