Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
diogok committed Aug 12, 2016
0 parents commit cc69ee5
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/public
barcodeserver
*.swp
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM alpine:3.1

RUN mkdir -p /opt/barcode/public
VOLUME /opt/barcode/public

RUN apk add --update ca-certificates
COPY ./barcodeserver /opt/barcode/barcodeserver
CMD ["/opt/barcode/barcodeserver"]

23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
project = barcodeserver

all: build

arm:
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -a -tags netgo -ldflags '-w'

build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w'

clean:
rm petals

docker: build
docker build -t diogok/$(project) .

docker-arm: arm
docker build -t diogok/$(project):arm .

push:
docker push diogok/$(project)


38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# BarCodeServer

Simple HTTP API around [https://github.com/boombuler/barcode](https://github.com/boombuler/barcode).

## Api Usage

Simply issue a get using the type of barcode desired as path and the content as queryString content and it will return a redirect to generated png.

$ curl -X GET http://localhost:8080/datamatrix?content=Whatever%20data

Available types:

* codabar
* code128
* code39
* ean
* datamatrix
* qr
* 2of5

In case of error it will return Bad Request 400 and error in plain/text.

## Deploy

Using the binary, download from the release page and run the binary and it will bind to port 8080.

Using docker:

$ docker run -p 8080:8080 -v /tmp/barcodes:/opt/barcode/public diogok/barcodeserver


It will save generated code at public folder. You can delete generated artefacts and if requested server will regenerate.


## License

MIT , same as [https://github.com/boombuler/barcode](https://github.com/boombuler/barcode).

207 changes: 207 additions & 0 deletions barcodeserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package main

import (
"bufio"
"crypto/sha1"
"encoding/hex"
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/codabar"
"github.com/boombuler/barcode/code128"
"github.com/boombuler/barcode/code39"
"github.com/boombuler/barcode/datamatrix"
"github.com/boombuler/barcode/ean"
"github.com/boombuler/barcode/qr"
"github.com/boombuler/barcode/twooffive"
"github.com/julienschmidt/httprouter"
"image/png"
"log"
"net/http"
"os"
"strconv"
)

func IdToPath(id string) string {
hasher := sha1.New()
hasher.Write([]byte(id))
hash := hex.EncodeToString(hasher.Sum(nil))
path := fmt.Sprintf("%s/%s/%s.png", hash[0:2], hash[2:4], hash)
os.MkdirAll(fmt.Sprintf("public/%s/%s", hash[0:2], hash[2:4]), 0755)
return path
}

func Get(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
bartype := p.ByName("type")
content := r.URL.Query().Get("content")

swidth := r.URL.Query().Get("width")
sheight := r.URL.Query().Get("height")

if swidth == "" {
swidth = "0"
}
if sheight == "" {
sheight = "0"
}

width, werr := strconv.Atoi(swidth)
if werr != nil {
log.Println(werr)
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error: %s", werr)
return
}
height, herr := strconv.Atoi(sheight)
if herr != nil {
log.Println(herr)
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error: %s", herr)
return
}

id := fmt.Sprintf("%s:%s:%d:%d", bartype, content, width, height)
path := IdToPath(id)
realPath := fmt.Sprintf("public/%s", path)

if _, err := os.Stat(realPath); err == nil {
http.Redirect(w, r, fmt.Sprintf("/%s", path), 307)
return
}

var err error
var initialBarcode barcode.Barcode

switch bartype {
case "datamatrix":
initialBarcode, err = datamatrix.Encode(content)
if width == 0 {
width = 256
}
if height == 0 {
height = 256
}
case "qr":
initialBarcode, err = qr.Encode(content, qr.Q, qr.Auto)
if width == 0 {
width = 256
}
if height == 0 {
height = 256
}
case "codabar":
initialBarcode, err = codabar.Encode(content)
if width == 0 {
width = 256
}
if height == 0 {
height = 50
}
case "code128":
initialBarcode, err = code128.Encode(content)
if width == 0 {
width = 256
}
if height == 0 {
height = 25
}
case "code39":
initialBarcode, err = code39.Encode(content, true, true)
if width == 0 {
width = 256
}
if height == 0 {
height = 25
}
case "ean":
initialBarcode, err = ean.Encode(content)
if width == 0 {
width = 256
}
if height == 0 {
height = 25
}
case "2of5":
initialBarcode, err = twooffive.Encode(content, true)
if width == 0 {
width = 256
}
if height == 0 {
height = 25
}
case "twooffive":
initialBarcode, err = twooffive.Encode(content, true)
if width == 0 {
width = 256
}
if height == 0 {
height = 25
}
}

if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error: %s", err)
return
} else if bartype == "" || initialBarcode == nil {
log.Println("Bad type")
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error: %s", "Bad bar type")
return
} else {
var serr error
var finalBarcode barcode.Barcode
if width != 0 && height != 0 {
finalBarcode, serr = barcode.Scale(initialBarcode, width, height)
} else {
finalBarcode = initialBarcode
}
if serr != nil {
log.Println(serr)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error: %s", serr)
return
}

file, ferr := os.Create(realPath)
if ferr != nil {
log.Println(ferr)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error: %s", ferr)
return
}
defer file.Close()

writer := bufio.NewWriter(file)
perr := png.Encode(writer, finalBarcode)
if perr != nil {
log.Println(perr)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error: %s", perr)
return
}
writer.Flush()

http.Redirect(w, r, fmt.Sprintf("/%s", path), 307)
}
}

func main() {
sport := os.Getenv("PORT")
var port string
if len(sport) > 2 {
port = sport
} else {
port = "8080"
}

log.Printf("Binding at 0.0.0.0:%s", port)

router := httprouter.New()
router.NotFound = http.FileServer(http.Dir("public"))

router.GET("/", Get)
router.GET("/:type", Get)

log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), router))
}
1 change: 1 addition & 0 deletions public/.placeholder
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder

0 comments on commit cc69ee5

Please sign in to comment.