Skip to content

Commit

Permalink
Add QR support (#13)
Browse files Browse the repository at this point in the history
* Remove ioutil

* Add qr codes
  • Loading branch information
jdtw authored Nov 2, 2022
1 parent 5a5b184 commit 33447d9
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/jackc/pgx/v4 v4.17.2
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXY
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
Expand Down
3 changes: 1 addition & 2 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"path"
"time"
Expand Down Expand Up @@ -131,7 +130,7 @@ func marshal(m proto.Message) (io.Reader, error) {
}

func unmarshalBody(resp *http.Response, m proto.Message) error {
b, err := ioutil.ReadAll(resp.Body)
b, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/links/api.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package links

import (
"io/ioutil"
"io"
"log"
"net/http"
"net/url"
Expand Down Expand Up @@ -54,7 +54,7 @@ func (s *server) get() authHandler {
func (s *server) put() authHandler {
return func(w http.ResponseWriter, r *http.Request, sub string) {
l := mux.Vars(r)["link"]
data, err := ioutil.ReadAll(r.Body)
data, err := io.ReadAll(r.Body)
if err != nil {
internalError(w, err)
return
Expand Down
5 changes: 2 additions & 3 deletions pkg/links/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
Expand Down Expand Up @@ -244,9 +243,9 @@ func marshal(t *testing.T, m proto.Message) io.Reader {

func unmarshal(t *testing.T, r io.Reader, m proto.Message) {
t.Helper()
b, err := ioutil.ReadAll(r)
b, err := io.ReadAll(r)
if err != nil {
t.Fatalf("ioutil.ReadAll failed: %v", err)
t.Fatalf("os.ReadAll failed: %v", err)
}
if err := protojson.Unmarshal(b, m); err != nil {
t.Fatalf("protojson.Unmarshal failed: %v", err)
Expand Down
27 changes: 27 additions & 0 deletions pkg/links/redirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"net/http"
"net/url"
"strings"

qrcode "github.com/skip2/go-qrcode"
)

// Index is used for special handling for the root path; it is stored
Expand All @@ -23,6 +25,17 @@ func (s *server) redirect() http.HandlerFunc {
key = Index
}

// If prefixed with the /qr/ path, show a QR instead of redirecting.
qr := false
if key == "qr" {
qr = true
if len(paths) == 0 {
key = Index
} else {
key, paths = paths[0], paths[1:]
}
}

// Look up the key, and unmarshal the LinkEntry from the DB
key = strings.ReplaceAll(key, "-", "")
le, err := s.store.Get(r.Context(), key)
Expand Down Expand Up @@ -58,7 +71,21 @@ func (s *server) redirect() http.HandlerFunc {
if rq := r.URL.RawQuery; rq != "" {
loc.RawQuery = rq
}
if qr {
writeQR(w, loc)
return
}
log.Printf("redirecting %s to %s", r.URL, loc)
http.Redirect(w, r, loc.String(), http.StatusFound)
}
}

func writeQR(w http.ResponseWriter, u *url.URL) {
png, err := qrcode.Encode(u.String(), qrcode.High, 256)
if err != nil {
log.Printf("qrcode.Encode(%s) failed: %v", u, err)
internalError(w, err)
}
w.Header().Set("Content-Type", "image/png")
w.Write(png)
}
42 changes: 42 additions & 0 deletions pkg/links/redirect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,45 @@ func TestRedirect(t *testing.T) {
}
}
}

func TestQR(t *testing.T) {
tests := []struct {
key string
value string
get string
}{{
key: Index,
value: "https://example.com",
get: "/qr",
}, {
key: "foo",
value: "https://example.com",
get: "/qr/foo",
}}

for _, tc := range tests {
t.Logf("test %q", tc.key)

s := NewMemStore()
s.Put(context.Background(), tc.key, &pb.Link{Uri: tc.value})

req, err := http.NewRequest("GET", tc.get, nil)
if err != nil {
t.Errorf("NewRequest(%v) failed: %v", tc.get, err)
continue
}

rr := httptest.NewRecorder()
srv := NewHandler(s, nil)
srv.ServeHTTP(rr, req)
res := rr.Result()

if res.StatusCode != http.StatusOK {
t.Errorf("result %+v: got code %v, want OK", res, res.StatusCode)
continue
}
if ct := res.Header["Content-Type"]; len(ct) != 1 || ct[0] != "image/png" {
t.Errorf("got Content-Type %v, want image/png", ct)
}
}
}
4 changes: 4 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ echo "Testing hyphens..."
result=$(curl -s "${ADDR}/f-o-o" -o /dev/null -w "${TEST_OUTPUT}")
test "${result}" = "302 http://www.example.com/"

echo "Testing QR code..."
result=$(curl -s "${ADDR}/qr/foo" -o /dev/null -w '%{http_code} %{content_type}')
test "${result}" = "200 image/png"

echo "Testing get redirect..."
"${TEST_DIR}/client" --priv "${PRIV}" \
--addr "${ADDR}" \
Expand Down

0 comments on commit 33447d9

Please sign in to comment.