aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-08-02 22:33:45 +0200
committerMichael Muré <batolettre@gmail.com>2018-08-02 22:33:45 +0200
commited8f7eca9a8e0d1c448a7cc6240e2b7e357cf354 (patch)
tree0f02849e3e91e7ee543235e043185bb86275478b
parent9488467c754230288934dde4a49b9046e658986c (diff)
downloadgit-bug-ed8f7eca9a8e0d1c448a7cc6240e2b7e357cf354.tar.gz
webui: add the http handlers for read/write git blob for media in comments
-rw-r--r--commands/webui.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/commands/webui.go b/commands/webui.go
index b31013ad..d5560180 100644
--- a/commands/webui.go
+++ b/commands/webui.go
@@ -1,16 +1,22 @@
package commands
import (
+ "bytes"
+ "encoding/json"
"fmt"
"github.com/MichaelMure/git-bug/graphql"
+ "github.com/MichaelMure/git-bug/repository"
+ "github.com/MichaelMure/git-bug/util"
"github.com/MichaelMure/git-bug/webui"
"github.com/gorilla/mux"
"github.com/phayes/freeport"
"github.com/skratchdot/open-golang/open"
"github.com/spf13/cobra"
"github.com/vektah/gqlgen/handler"
+ "io/ioutil"
"log"
"net/http"
+ "time"
)
var port int
@@ -36,6 +42,8 @@ func runWebUI(cmd *cobra.Command, args []string) error {
// Routes
router.Path("/playground").Handler(handler.Playground("git-bug", "/graphql"))
router.Path("/graphql").Handler(graphql.NewHandler(repo))
+ router.Path("/gitfile/{hash}").Handler(newGitFileHandler(repo))
+ router.Path("/upload").Methods("POST").Handler(newGitUploadFileHandler(repo))
router.PathPrefix("/").Handler(http.FileServer(webui.WebUIAssets))
open.Run(webUiAddr)
@@ -45,6 +53,109 @@ func runWebUI(cmd *cobra.Command, args []string) error {
return nil
}
+type gitFileHandler struct {
+ repo repository.Repo
+}
+
+func newGitFileHandler(repo repository.Repo) http.Handler {
+ return &gitFileHandler{
+ repo: repo,
+ }
+}
+
+func (gfh *gitFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ hash := mux.Vars(r)["hash"]
+
+ if !isGitHash(hash) {
+ http.Error(rw, "invalid git hash", http.StatusBadRequest)
+ return
+ }
+
+ // TODO: this mean that the whole file will he buffered in memory
+ // This can be a problem for big files. There might be a way around
+ // that by implementing a io.ReadSeeker that would read and discard
+ // data when a seek is called.
+ data, err := gfh.repo.ReadData(util.Hash(hash))
+ if err != nil {
+ http.Error(rw, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ http.ServeContent(rw, r, "", time.Now(), bytes.NewReader(data))
+}
+
+type gitUploadFileHandler struct {
+ repo repository.Repo
+}
+
+func newGitUploadFileHandler(repo repository.Repo) http.Handler {
+ return &gitUploadFileHandler{
+ repo: repo,
+ }
+}
+
+func (gufh *gitUploadFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ // 100MB (github limit)
+ var maxUploadSize int64 = 100 * 1000 * 1000
+ r.Body = http.MaxBytesReader(rw, r.Body, maxUploadSize)
+ if err := r.ParseMultipartForm(maxUploadSize); err != nil {
+ http.Error(rw, "file too big (100MB max)", http.StatusBadRequest)
+ return
+ }
+
+ file, _, err := r.FormFile("uploadfile")
+ if err != nil {
+ http.Error(rw, "invalid file", http.StatusBadRequest)
+ return
+ }
+ defer file.Close()
+ fileBytes, err := ioutil.ReadAll(file)
+ if err != nil {
+ http.Error(rw, "invalid file", http.StatusBadRequest)
+ return
+ }
+
+ filetype := http.DetectContentType(fileBytes)
+ if filetype != "image/jpeg" && filetype != "image/jpg" &&
+ filetype != "image/gif" && filetype != "image/png" {
+ http.Error(rw, "invalid file type", http.StatusBadRequest)
+ return
+ }
+
+ hash, err := gufh.repo.StoreData(fileBytes)
+ if err != nil {
+ http.Error(rw, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ type response struct {
+ Hash string `json:"hash"`
+ }
+
+ resp := response{Hash: string(hash)}
+
+ js, err := json.Marshal(resp)
+ if err != nil {
+ http.Error(rw, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ rw.Header().Set("Content-Type", "application/json")
+ rw.Write(js)
+}
+
+func isGitHash(s string) bool {
+ if len(s) != 40 {
+ return false
+ }
+ for _, r := range s {
+ if (r < 'a' || r > 'z') && (r < '0' || r > '9') {
+ return false
+ }
+ }
+ return true
+}
+
var webUICmd = &cobra.Command{
Use: "webui",
Short: "Launch the web UI",