Skip to content

Commit cc69ee5

Browse files
committed
Initial commit
0 parents  commit cc69ee5

6 files changed

Lines changed: 281 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/public
2+
barcodeserver
3+
*.swp

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM alpine:3.1
2+
3+
RUN mkdir -p /opt/barcode/public
4+
VOLUME /opt/barcode/public
5+
6+
RUN apk add --update ca-certificates
7+
COPY ./barcodeserver /opt/barcode/barcodeserver
8+
CMD ["/opt/barcode/barcodeserver"]
9+

Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
project = barcodeserver
2+
3+
all: build
4+
5+
arm:
6+
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -a -tags netgo -ldflags '-w'
7+
8+
build:
9+
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w'
10+
11+
clean:
12+
rm petals
13+
14+
docker: build
15+
docker build -t diogok/$(project) .
16+
17+
docker-arm: arm
18+
docker build -t diogok/$(project):arm .
19+
20+
push:
21+
docker push diogok/$(project)
22+
23+

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# BarCodeServer
2+
3+
Simple HTTP API around [https://github.com/boombuler/barcode](https://github.com/boombuler/barcode).
4+
5+
## Api Usage
6+
7+
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.
8+
9+
$ curl -X GET http://localhost:8080/datamatrix?content=Whatever%20data
10+
11+
Available types:
12+
13+
* codabar
14+
* code128
15+
* code39
16+
* ean
17+
* datamatrix
18+
* qr
19+
* 2of5
20+
21+
In case of error it will return Bad Request 400 and error in plain/text.
22+
23+
## Deploy
24+
25+
Using the binary, download from the release page and run the binary and it will bind to port 8080.
26+
27+
Using docker:
28+
29+
$ docker run -p 8080:8080 -v /tmp/barcodes:/opt/barcode/public diogok/barcodeserver
30+
31+
32+
It will save generated code at public folder. You can delete generated artefacts and if requested server will regenerate.
33+
34+
35+
## License
36+
37+
MIT , same as [https://github.com/boombuler/barcode](https://github.com/boombuler/barcode).
38+

barcodeserver.go

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"crypto/sha1"
6+
"encoding/hex"
7+
"fmt"
8+
"github.com/boombuler/barcode"
9+
"github.com/boombuler/barcode/codabar"
10+
"github.com/boombuler/barcode/code128"
11+
"github.com/boombuler/barcode/code39"
12+
"github.com/boombuler/barcode/datamatrix"
13+
"github.com/boombuler/barcode/ean"
14+
"github.com/boombuler/barcode/qr"
15+
"github.com/boombuler/barcode/twooffive"
16+
"github.com/julienschmidt/httprouter"
17+
"image/png"
18+
"log"
19+
"net/http"
20+
"os"
21+
"strconv"
22+
)
23+
24+
func IdToPath(id string) string {
25+
hasher := sha1.New()
26+
hasher.Write([]byte(id))
27+
hash := hex.EncodeToString(hasher.Sum(nil))
28+
path := fmt.Sprintf("%s/%s/%s.png", hash[0:2], hash[2:4], hash)
29+
os.MkdirAll(fmt.Sprintf("public/%s/%s", hash[0:2], hash[2:4]), 0755)
30+
return path
31+
}
32+
33+
func Get(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
34+
bartype := p.ByName("type")
35+
content := r.URL.Query().Get("content")
36+
37+
swidth := r.URL.Query().Get("width")
38+
sheight := r.URL.Query().Get("height")
39+
40+
if swidth == "" {
41+
swidth = "0"
42+
}
43+
if sheight == "" {
44+
sheight = "0"
45+
}
46+
47+
width, werr := strconv.Atoi(swidth)
48+
if werr != nil {
49+
log.Println(werr)
50+
w.WriteHeader(http.StatusBadRequest)
51+
fmt.Fprintf(w, "Error: %s", werr)
52+
return
53+
}
54+
height, herr := strconv.Atoi(sheight)
55+
if herr != nil {
56+
log.Println(herr)
57+
w.WriteHeader(http.StatusBadRequest)
58+
fmt.Fprintf(w, "Error: %s", herr)
59+
return
60+
}
61+
62+
id := fmt.Sprintf("%s:%s:%d:%d", bartype, content, width, height)
63+
path := IdToPath(id)
64+
realPath := fmt.Sprintf("public/%s", path)
65+
66+
if _, err := os.Stat(realPath); err == nil {
67+
http.Redirect(w, r, fmt.Sprintf("/%s", path), 307)
68+
return
69+
}
70+
71+
var err error
72+
var initialBarcode barcode.Barcode
73+
74+
switch bartype {
75+
case "datamatrix":
76+
initialBarcode, err = datamatrix.Encode(content)
77+
if width == 0 {
78+
width = 256
79+
}
80+
if height == 0 {
81+
height = 256
82+
}
83+
case "qr":
84+
initialBarcode, err = qr.Encode(content, qr.Q, qr.Auto)
85+
if width == 0 {
86+
width = 256
87+
}
88+
if height == 0 {
89+
height = 256
90+
}
91+
case "codabar":
92+
initialBarcode, err = codabar.Encode(content)
93+
if width == 0 {
94+
width = 256
95+
}
96+
if height == 0 {
97+
height = 50
98+
}
99+
case "code128":
100+
initialBarcode, err = code128.Encode(content)
101+
if width == 0 {
102+
width = 256
103+
}
104+
if height == 0 {
105+
height = 25
106+
}
107+
case "code39":
108+
initialBarcode, err = code39.Encode(content, true, true)
109+
if width == 0 {
110+
width = 256
111+
}
112+
if height == 0 {
113+
height = 25
114+
}
115+
case "ean":
116+
initialBarcode, err = ean.Encode(content)
117+
if width == 0 {
118+
width = 256
119+
}
120+
if height == 0 {
121+
height = 25
122+
}
123+
case "2of5":
124+
initialBarcode, err = twooffive.Encode(content, true)
125+
if width == 0 {
126+
width = 256
127+
}
128+
if height == 0 {
129+
height = 25
130+
}
131+
case "twooffive":
132+
initialBarcode, err = twooffive.Encode(content, true)
133+
if width == 0 {
134+
width = 256
135+
}
136+
if height == 0 {
137+
height = 25
138+
}
139+
}
140+
141+
if err != nil {
142+
log.Println(err)
143+
w.WriteHeader(http.StatusInternalServerError)
144+
fmt.Fprintf(w, "Error: %s", err)
145+
return
146+
} else if bartype == "" || initialBarcode == nil {
147+
log.Println("Bad type")
148+
w.WriteHeader(http.StatusBadRequest)
149+
fmt.Fprintf(w, "Error: %s", "Bad bar type")
150+
return
151+
} else {
152+
var serr error
153+
var finalBarcode barcode.Barcode
154+
if width != 0 && height != 0 {
155+
finalBarcode, serr = barcode.Scale(initialBarcode, width, height)
156+
} else {
157+
finalBarcode = initialBarcode
158+
}
159+
if serr != nil {
160+
log.Println(serr)
161+
w.WriteHeader(http.StatusInternalServerError)
162+
fmt.Fprintf(w, "Error: %s", serr)
163+
return
164+
}
165+
166+
file, ferr := os.Create(realPath)
167+
if ferr != nil {
168+
log.Println(ferr)
169+
w.WriteHeader(http.StatusInternalServerError)
170+
fmt.Fprintf(w, "Error: %s", ferr)
171+
return
172+
}
173+
defer file.Close()
174+
175+
writer := bufio.NewWriter(file)
176+
perr := png.Encode(writer, finalBarcode)
177+
if perr != nil {
178+
log.Println(perr)
179+
w.WriteHeader(http.StatusInternalServerError)
180+
fmt.Fprintf(w, "Error: %s", perr)
181+
return
182+
}
183+
writer.Flush()
184+
185+
http.Redirect(w, r, fmt.Sprintf("/%s", path), 307)
186+
}
187+
}
188+
189+
func main() {
190+
sport := os.Getenv("PORT")
191+
var port string
192+
if len(sport) > 2 {
193+
port = sport
194+
} else {
195+
port = "8080"
196+
}
197+
198+
log.Printf("Binding at 0.0.0.0:%s", port)
199+
200+
router := httprouter.New()
201+
router.NotFound = http.FileServer(http.Dir("public"))
202+
203+
router.GET("/", Get)
204+
router.GET("/:type", Get)
205+
206+
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), router))
207+
}

public/.placeholder

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
placeholder

0 commit comments

Comments
 (0)