aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/db/redis/image.go21
-rw-r--r--internal/db/redis/redis.go2
-rw-r--r--internal/fs/fs.go18
-rw-r--r--internal/image/handler.go33
-rw-r--r--internal/image/image_test.go42
-rw-r--r--internal/image/model.go1
-rw-r--r--internal/image/repo.go1
-rw-r--r--internal/image/service.go46
8 files changed, 140 insertions, 24 deletions
diff --git a/internal/db/redis/image.go b/internal/db/redis/image.go
index 6814fb7..1f4e8fa 100644
--- a/internal/db/redis/image.go
+++ b/internal/db/redis/image.go
@@ -9,7 +9,7 @@ import (
"git.ofmax.li/iserv/internal/image"
)
-const V1FilePathFmt = "filepath:up/%s"
+const V1FilePathFmt = "v1imagepost:%s"
// ImageRepo deps. for storage
type ImageRepo struct {
@@ -23,13 +23,30 @@ func NewRedisImageRepo(conn *redis.Pool) *ImageRepo {
}
}
+func fileKey(filename, V1FilePathFmt string) string {
+ return fmt.Sprintf(V1FilePathFmt, filename)
+}
+
func (r *ImageRepo) AddNewFile(filename string, meta *image.PostMeta, timeout int) error {
conn := r.db.Get()
defer conn.Close()
- key := fmt.Sprintf(V1FilePathFmt, filename)
+ key := fileKey(filename, V1FilePathFmt)
_, err := conn.Do("HMSET", redis.Args{}.Add(key).AddFlat(meta)...)
if err != nil {
log.Fatal(err)
}
return err
}
+
+func (r *ImageRepo) GetFile(fileUrl string) (*image.PostMeta, error) {
+ conn := r.db.Get()
+ defer conn.Close()
+ imageMeta := &image.PostMeta{}
+ key := fileKey(fileUrl, V1FilePathFmt)
+ res, err := redis.Values(conn.Do("HGETALL", key))
+ if err != nil {
+ return &image.PostMeta{}, err
+ }
+ err = redis.ScanStruct(res, imageMeta)
+ return imageMeta, err
+}
diff --git a/internal/db/redis/redis.go b/internal/db/redis/redis.go
index d769bb4..f9147be 100644
--- a/internal/db/redis/redis.go
+++ b/internal/db/redis/redis.go
@@ -5,7 +5,7 @@ import (
"github.com/gomodule/redigo/redis"
- "gitlab.com/grumps/environ"
+ "go.ofmax.li/environ"
)
var redisServer = environ.GetEnv("AUTH_REDIS", "localhost:6379")
diff --git a/internal/fs/fs.go b/internal/fs/fs.go
new file mode 100644
index 0000000..7b2704b
--- /dev/null
+++ b/internal/fs/fs.go
@@ -0,0 +1,18 @@
+package fs
+
+import (
+ "net/http"
+ "strings"
+
+ "github.com/go-chi/chi"
+)
+
+func NewHandler(path string) http.HandlerFunc {
+ filesDir := http.Dir(path)
+ return func(w http.ResponseWriter, r *http.Request) {
+ rctx := chi.RouteContext(r.Context())
+ pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
+ fs := http.StripPrefix(pathPrefix, http.FileServer(filesDir))
+ fs.ServeHTTP(w, r)
+ }
+}
diff --git a/internal/image/handler.go b/internal/image/handler.go
index 8988a58..2db4c40 100644
--- a/internal/image/handler.go
+++ b/internal/image/handler.go
@@ -5,6 +5,8 @@ import (
"io/ioutil"
"log"
"net/http"
+
+ "github.com/go-chi/chi"
)
var fileTypes = map[string]string{
@@ -27,9 +29,22 @@ type imageHandler struct {
service Servicer
}
+// GetImage handler for returning an image
func (h *imageHandler) GetImage(w http.ResponseWriter, r *http.Request) {
- log.Print("serving image")
- http.ServeFile(w, r, "foo.jpg")
+ fileID := chi.URLParam(r, "fileName")
+ fileMeta, err := h.service.GetFile(fileID)
+ if err != nil {
+ w.WriteHeader(400)
+ log.Printf("error: %+v", err)
+ w.Write([]byte("WTF Incorrect Content Type"))
+ }
+ fileUrl := fmt.Sprintf("/f/%s", fileMeta.FilePath)
+ data := struct {
+ ImageUrl string
+ }{
+ fileUrl,
+ }
+ h.service.Render(w, "image.tmpl", data)
}
// PostImage handler for creating an image post
@@ -39,6 +54,7 @@ func (h *imageHandler) PostImage(w http.ResponseWriter, r *http.Request) {
file, handler, err := r.FormFile("file")
if err != nil {
log.Printf("%s", err)
+ return
}
defer file.Close()
fileBytes, err := ioutil.ReadAll(file)
@@ -63,9 +79,14 @@ func (h *imageHandler) PostImage(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Incorrect Content Type"))
return
}
- fileID, err := h.service.NewID()
- fileName := fmt.Sprintf("%s.%s", fileID, extension)
- h.service.AddFile(fileName, fileBytes)
+ fileName, fileID, err := h.service.AddFile(extension, fileType, fileBytes)
+ if err != nil {
+ log.Printf("failed to write file")
+ w.WriteHeader(500)
+ w.Write([]byte("An Internal Error Occured"))
+ return
+ }
w.WriteHeader(201)
- w.Write([]byte("ok"))
+ w.Write([]byte(fmt.Sprintf("%s %s", fileName, fileID)))
+ return
}
diff --git a/internal/image/image_test.go b/internal/image/image_test.go
index 4a1aea9..3425213 100644
--- a/internal/image/image_test.go
+++ b/internal/image/image_test.go
@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
+ "log"
"mime/multipart"
"net/http"
"net/http/httptest"
@@ -11,6 +12,7 @@ import (
"os"
"path"
"path/filepath"
+ "runtime"
"strings"
"testing"
@@ -20,8 +22,22 @@ import (
db "git.ofmax.li/iserv/internal/db/redis"
"git.ofmax.li/iserv/internal/image"
+ "go.ofmax.li/tmpl"
)
+var (
+ projectRoot string
+)
+
+func init() {
+ _, filename, _, _ := runtime.Caller(0)
+ projectRoot := path.Join(path.Dir(filename), "../..")
+ err := os.Chdir(projectRoot)
+ if err != nil {
+ panic(err)
+ }
+}
+
// from go lang src https://golang.org/src/mime/multipart/writer.go
// there seems to be no way to set the content type.
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
@@ -67,7 +83,7 @@ func prepareRequest(t *testing.T, filename, mimeType string) (*multipart.Writer,
return writer, body, err
}
-func TestImage(t *testing.T) {
+func TestPostImage(t *testing.T) {
// setup redis for tests
conn := redigomock.NewConn()
pool := &redis.Pool{
@@ -75,7 +91,7 @@ func TestImage(t *testing.T) {
Dial: func() (redis.Conn, error) { return conn, nil },
MaxIdle: 10,
}
- conn.Command("HMSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData())
+ conn.Command("HMSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData())
repo := db.NewRedisImageRepo(pool)
// setup image package
@@ -83,13 +99,20 @@ func TestImage(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ cwd, _ := os.Getwd()
+ base := filepath.Join(cwd, "templates")
+ renderer, err := tmpl.NewHTMLTmpl(base)
+ if err != nil {
+ log.Fatal(err)
+ }
defer os.RemoveAll(imageBuildDir)
- imageService := image.NewService(repo, imageBuildDir)
+ imageService := image.NewService(repo, imageBuildDir, renderer)
imageHandler := image.NewHandler(imageService)
handler := http.HandlerFunc(imageHandler.PostImage)
// prep test with png
- writer, body, err := prepareRequest(t, "t.png", "image/png")
+ testImagePath := filepath.Join(projectRoot, "internal/image/t.png")
+ writer, body, err := prepareRequest(t, testImagePath, "image/png")
if err != nil {
t.Fatal(err)
}
@@ -107,7 +130,8 @@ func TestImage(t *testing.T) {
}
// incorrect mime
- writer, body, err = prepareRequest(t, "t.pdf", "application/pdf")
+ testImagePDF := filepath.Join(projectRoot, "internal/image/t.pdf")
+ writer, body, err = prepareRequest(t, testImagePDF, "application/pdf")
if err != nil {
t.Fatal(err)
}
@@ -124,7 +148,7 @@ func TestImage(t *testing.T) {
}
// sneaky mimetype check
- writer, body, err = prepareRequest(t, "t.png", "image/jpeg")
+ writer, body, err = prepareRequest(t, testImagePath, "image/jpeg")
if err != nil {
t.Fatal(err)
}
@@ -141,7 +165,6 @@ func TestImage(t *testing.T) {
}
// test image write path && ext
- // TODO
pngs, err := filepath.Glob(filepath.Join(imageBuildDir))
if err != nil {
t.Fatal(err)
@@ -149,4 +172,9 @@ func TestImage(t *testing.T) {
if len(pngs) != 1 {
t.Error("expected only 1 image to be found")
}
+
+}
+
+func TestGetImage(t *testing.T) {
+
}
diff --git a/internal/image/model.go b/internal/image/model.go
index 002ad8a..0d1cd60 100644
--- a/internal/image/model.go
+++ b/internal/image/model.go
@@ -5,4 +5,5 @@ type PostMeta struct {
FilePath string `redis:"file_path"`
CreatedAt string `redis:"created_at"`
UserID string `redis:"user_id"`
+ MimeType string `redis:"mime_type"`
}
diff --git a/internal/image/repo.go b/internal/image/repo.go
index a65ad49..39f6a56 100644
--- a/internal/image/repo.go
+++ b/internal/image/repo.go
@@ -3,4 +3,5 @@ package image
// Repo storage interface
type Repo interface {
AddNewFile(filename string, meta *PostMeta, timeout int) error
+ GetFile(fileUrl string) (*PostMeta, error)
}
diff --git a/internal/image/service.go b/internal/image/service.go
index dabbfe7..f953bfa 100644
--- a/internal/image/service.go
+++ b/internal/image/service.go
@@ -1,24 +1,32 @@
package image
import (
+ "fmt"
"io/ioutil"
"log"
+ "net/http"
"path"
"time"
"github.com/matoous/go-nanoid"
+ "github.com/pkg/errors"
+
+ "go.ofmax.li/tmpl"
)
// Servicer image management
type Servicer interface {
NewID() (string, error)
- AddFile(filename string, fileBytes []byte) error
+ AddFile(extension, fileType string, fileBytes []byte) (string, string, error)
+ GetFile(fileUrl string) (*PostMeta, error)
+ Render(w http.ResponseWriter, templateName string, data interface{}) error
}
// NewService new image service
-func NewService(repo Repo, storagePath string) *Service {
+func NewService(repo Repo, storagePath string, renderer *tmpl.HTML) *Service {
return &Service{repo,
storagePath,
+ renderer,
}
}
@@ -26,6 +34,12 @@ func NewService(repo Repo, storagePath string) *Service {
type Service struct {
db Repo
storagePath string
+ tmpl *tmpl.HTML
+}
+
+// Render renders templates
+func (is *Service) Render(w http.ResponseWriter, templateName string, data interface{}) error {
+ return is.tmpl.Render(w, templateName, data)
}
// NewID create an uniqueish ID
@@ -34,22 +48,38 @@ func (is *Service) NewID() (string, error) {
}
// AddFile writes to disk, writes meta to db
-func (is *Service) AddFile(fileName string, fileBytes []byte) error {
+func (is *Service) AddFile(extension, fileType string, fileBytes []byte) (string, string, error) {
+ fileID, err := is.NewID()
+ if err != nil {
+ return "", "", errors.Wrap(err, "generated id for fileID failed")
+ }
+ fileName := fmt.Sprintf("%s.%s", fileID, extension)
filePath := path.Join(is.storagePath, fileName)
if err := ioutil.WriteFile(filePath, fileBytes, 0750); err != nil {
log.Fatal(err)
- return err
+ return "", "", errors.Wrap(err, "couldn't write image file")
+ }
+ postID, err := is.NewID()
+ if err != nil {
+ return "", "", errors.Wrap(err, "generating postid for uuid")
}
t := time.Now().UTC()
postMeta := &PostMeta{
FilePath: fileName,
CreatedAt: t.Format(time.RFC3339),
UserID: "1",
+ MimeType: fileType,
}
- is.db.AddNewFile(fileName, postMeta, 946080000)
- if err := is.db.AddNewFile(fileName, postMeta, 946080000); err != nil {
+ is.db.AddNewFile(postID, postMeta, 946080000)
+ if err := is.db.AddNewFile(postID, postMeta, 946080000); err != nil {
log.Fatal(err)
- return err
+ return "", "", errors.Wrap(err, "couldn't write to redis")
}
- return nil
+ return fileName, postID, nil
+}
+
+// GetFile fetch file from db interface
+func (is *Service) GetFile(fileUrl string) (*PostMeta, error) {
+ result, err := is.db.GetFile(fileUrl)
+ return result, err
}