1
0
mirror of https://github.com/Luzifer/tex-api.git synced 2024-09-19 17:42:55 +00:00

Merge branch 'refactor'

This commit is contained in:
Knut Ahlers 2017-03-06 22:09:40 +01:00
commit 5aaeab6fcf
Signed by: luzifer
GPG Key ID: DC2729FDD34BE99E
4 changed files with 133 additions and 138 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
tex-api

4
Makefile Normal file
View File

@ -0,0 +1,4 @@
auto-hook-pre-push:
test:
gometalinter -D errcheck -D gas --deadline 20s .

104
assets.go Normal file
View File

@ -0,0 +1,104 @@
package main
import (
"archive/tar"
"archive/zip"
"bytes"
"io"
"os"
"path"
"path/filepath"
"strings"
"github.com/Luzifer/go_helpers/str"
uuid "github.com/satori/go.uuid"
)
func shouldPackFile(extension string) bool {
return str.StringInSlice(extension, []string{
".log",
".pdf",
})
}
func buildAssetsZIP(uid uuid.UUID) (io.Reader, error) {
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
basePath := pathFromUUID(uid, filenameOutputDir)
err := filepath.Walk(basePath, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !shouldPackFile(path.Ext(info.Name())) {
return nil
}
zipInfo, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
zipInfo.Name = strings.TrimLeft(strings.Replace(p, basePath, "", 1), "/\\")
zipFile, err := w.CreateHeader(zipInfo)
if err != nil {
return err
}
osFile, err := os.Open(p)
if err != nil {
return err
}
io.Copy(zipFile, osFile)
osFile.Close()
return nil
})
if err != nil {
return nil, err
}
return buf, w.Close()
}
func buildAssetsTAR(uid uuid.UUID) (io.Reader, error) {
buf := new(bytes.Buffer)
w := tar.NewWriter(buf)
basePath := pathFromUUID(uid, filenameOutputDir)
err := filepath.Walk(basePath, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !shouldPackFile(path.Ext(info.Name())) {
return nil
}
tarInfo, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
tarInfo.Name = strings.TrimLeft(strings.Replace(p, basePath, "", 1), "/\\")
err = w.WriteHeader(tarInfo)
if err != nil {
return err
}
osFile, err := os.Open(p)
if err != nil {
return err
}
io.Copy(w, osFile)
osFile.Close()
return nil
})
if err != nil {
return nil, err
}
return buf, w.Close()
}

162
main.go
View File

@ -1,9 +1,6 @@
package main package main
import ( import (
"archive/tar"
"archive/zip"
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -13,12 +10,9 @@ import (
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/Luzifer/go_helpers/str"
"github.com/Luzifer/rconfig" "github.com/Luzifer/rconfig"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -53,17 +47,17 @@ const (
sleepBase = 1.5 sleepBase = 1.5
) )
type statusOutput struct { type jobStatus struct {
UUID string `json:"uuid"` UUID string `json:"uuid"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
Status status `json:"status"` Status status `json:"status"`
} }
func loadStatusByUUID(uid uuid.UUID) (*statusOutput, error) { func loadStatusByUUID(uid uuid.UUID) (*jobStatus, error) {
statusFile := pathFromUUID(uid, filenameStatus) statusFile := pathFromUUID(uid, filenameStatus)
status := statusOutput{} status := jobStatus{}
if f, err := os.Open(statusFile); err == nil { if f, err := os.Open(statusFile); err == nil {
defer f.Close() defer f.Close()
if err = json.NewDecoder(f).Decode(&status); err != nil { if err = json.NewDecoder(f).Decode(&status); err != nil {
@ -76,12 +70,12 @@ func loadStatusByUUID(uid uuid.UUID) (*statusOutput, error) {
return &status, nil return &status, nil
} }
func (s *statusOutput) UpdateStatus(st status) { func (s *jobStatus) UpdateStatus(st status) {
s.Status = st s.Status = st
s.UpdatedAt = time.Now() s.UpdatedAt = time.Now()
} }
func (s statusOutput) Save() error { func (s jobStatus) Save() error {
uid, _ := uuid.FromString(s.UUID) uid, _ := uuid.FromString(s.UUID)
f, err := os.Create(pathFromUUID(uid, filenameStatus)) f, err := os.Create(pathFromUUID(uid, filenameStatus))
if err != nil { if err != nil {
@ -120,6 +114,11 @@ func main() {
log.Fatalf("%s", http.ListenAndServe(cfg.Listen, router)) log.Fatalf("%s", http.ListenAndServe(cfg.Listen, router))
} }
func serverErrorf(res http.ResponseWriter, tpl string, args ...interface{}) {
log.Errorf(tpl, args...)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
}
func pathFromUUID(uid uuid.UUID, filename string) string { func pathFromUUID(uid uuid.UUID, filename string) string {
return path.Join(cfg.StorageDir, uid.String(), filename) return path.Join(cfg.StorageDir, uid.String(), filename)
} }
@ -139,27 +138,24 @@ func startNewJob(res http.ResponseWriter, r *http.Request) {
if f, err := os.Create(inputFile); err == nil { if f, err := os.Create(inputFile); err == nil {
defer f.Close() defer f.Close()
if _, err := io.Copy(f, r.Body); err != nil { if _, copyErr := io.Copy(f, r.Body); err != nil {
log.Errorf("Unable to copy input file %q: %s", inputFile, err) serverErrorf(res, "Unable to copy input file %q: %s", inputFile, copyErr)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
f.Sync() f.Sync()
} else { } else {
log.Errorf("Unable to write input file %q: %s", inputFile, err) serverErrorf(res, "Unable to write input file %q: %s", inputFile, err)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
status := statusOutput{ status := jobStatus{
UUID: jobUUID.String(), UUID: jobUUID.String(),
CreatedAt: time.Now(), CreatedAt: time.Now(),
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
Status: statusCreated, Status: statusCreated,
} }
if err := status.Save(); err != nil { if err := status.Save(); err != nil {
log.Errorf("Unable to create status file %q: %s", statusFile, err) serverErrorf(res, "Unable to create status file %q: %s", statusFile, err)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
@ -169,23 +165,6 @@ func startNewJob(res http.ResponseWriter, r *http.Request) {
http.Redirect(res, r, u.String(), http.StatusFound) http.Redirect(res, r, u.String(), http.StatusFound)
} }
func checkJobStatus(res http.ResponseWriter, r *http.Request) (uuid.UUID, string) {
vars := mux.Vars(r)
uid, err := uuid.FromString(vars["uid"])
if err != nil {
http.Error(res, "UUID had unexpected format!", http.StatusBadRequest)
return uid, ""
}
statusFile := pathFromUUID(uid, filenameStatus)
if _, err := os.Stat(statusFile); err != nil {
http.Error(res, "Status for this UUID not found.", http.StatusNotFound)
return uid, ""
}
return uid, statusFile
}
func getJobStatus(res http.ResponseWriter, r *http.Request) { func getJobStatus(res http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
uid, err := uuid.FromString(vars["uid"]) uid, err := uuid.FromString(vars["uid"])
@ -195,14 +174,12 @@ func getJobStatus(res http.ResponseWriter, r *http.Request) {
} }
if status, err := loadStatusByUUID(uid); err == nil { if status, err := loadStatusByUUID(uid); err == nil {
if err := json.NewEncoder(res).Encode(status); err != nil { if encErr := json.NewEncoder(res).Encode(status); err != nil {
log.Errorf("Unable to serialize status file: %s", err) serverErrorf(res, "Unable to serialize status file: %s", encErr)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
} else { } else {
log.Errorf("Unable to read status file: %s", err) serverErrorf(res, "Unable to read status file: %s", err)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
} }
@ -217,7 +194,7 @@ func waitForJob(res http.ResponseWriter, r *http.Request) {
var loop int var loop int
if v := r.URL.Query().Get("loop"); v != "" { if v := r.URL.Query().Get("loop"); v != "" {
if pv, err := strconv.Atoi(v); err == nil { if pv, convErr := strconv.Atoi(v); convErr == nil {
loop = pv loop = pv
} }
} }
@ -225,8 +202,7 @@ func waitForJob(res http.ResponseWriter, r *http.Request) {
status, err := loadStatusByUUID(uid) status, err := loadStatusByUUID(uid)
if err != nil { if err != nil {
log.Errorf("Unable to read status file: %s", err) serverErrorf(res, "Unable to read status file: %s", err)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
@ -252,95 +228,6 @@ func waitForJob(res http.ResponseWriter, r *http.Request) {
} }
} }
func shouldPackFile(extension string) bool {
return str.StringInSlice(extension, []string{
".log",
".pdf",
})
}
func buildAssetsZIP(uid uuid.UUID) (io.Reader, error) {
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
basePath := pathFromUUID(uid, filenameOutputDir)
err := filepath.Walk(basePath, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !shouldPackFile(path.Ext(info.Name())) {
return nil
}
zipInfo, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
zipInfo.Name = strings.TrimLeft(strings.Replace(p, basePath, "", 1), "/\\")
zipFile, err := w.CreateHeader(zipInfo)
if err != nil {
return err
}
osFile, err := os.Open(p)
if err != nil {
return err
}
io.Copy(zipFile, osFile)
osFile.Close()
return nil
})
if err != nil {
return nil, err
}
return buf, w.Close()
}
func buildAssetsTAR(uid uuid.UUID) (io.Reader, error) {
buf := new(bytes.Buffer)
w := tar.NewWriter(buf)
basePath := pathFromUUID(uid, filenameOutputDir)
err := filepath.Walk(basePath, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !shouldPackFile(path.Ext(info.Name())) {
return nil
}
tarInfo, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
tarInfo.Name = strings.TrimLeft(strings.Replace(p, basePath, "", 1), "/\\")
err = w.WriteHeader(tarInfo)
if err != nil {
return err
}
osFile, err := os.Open(p)
if err != nil {
return err
}
io.Copy(w, osFile)
osFile.Close()
return nil
})
if err != nil {
return nil, err
}
return buf, w.Close()
}
func downloadAssets(res http.ResponseWriter, r *http.Request) { func downloadAssets(res http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
uid, err := uuid.FromString(vars["uid"]) uid, err := uuid.FromString(vars["uid"])
@ -364,8 +251,7 @@ func downloadAssets(res http.ResponseWriter, r *http.Request) {
} }
if err != nil { if err != nil {
log.Errorf("Unable to generate downloadable asset: %s", err) serverErrorf(res, "Unable to generate downloadable asset: %s", err)
http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError)
return return
} }
@ -390,14 +276,14 @@ func jobProcessor(uid uuid.UUID) {
status.UpdateStatus(statusStarted) status.UpdateStatus(statusStarted)
if err := status.Save(); err != nil { if err := status.Save(); err != nil {
log.Errorf("Unable to save status file: %s") log.Errorf("Unable to save status file")
return return
} }
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
status.UpdateStatus(statusError) status.UpdateStatus(statusError)
if err := status.Save(); err != nil { if err := status.Save(); err != nil {
log.Errorf("Unable to save status file: %s") log.Errorf("Unable to save status file")
return return
} }
return return
@ -405,7 +291,7 @@ func jobProcessor(uid uuid.UUID) {
status.UpdateStatus(statusFinished) status.UpdateStatus(statusFinished)
if err := status.Save(); err != nil { if err := status.Save(); err != nil {
log.Errorf("Unable to save status file: %s") log.Errorf("Unable to save status file")
return return
} }
} }