mirror of
https://github.com/Luzifer/tex-api.git
synced 2024-11-08 08:10:09 +00:00
Allow to request log instead of PDF on error
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
3364efc57b
commit
9c91061cf1
4 changed files with 31 additions and 10 deletions
|
@ -48,7 +48,7 @@ main.log
|
||||||
main.pdf
|
main.pdf
|
||||||
|
|
||||||
# Using the default-env and exchanging a TeX file for a PDF
|
# Using the default-env and exchanging a TeX file for a PDF
|
||||||
# curl -sSL -H 'Accept: application/pdf' --data-binary @main.tex -o main.pdf localhost:3000/job
|
# curl -L -H 'Accept: application/pdf' --data-binary @main.tex -OJ localhost:3000/job
|
||||||
```
|
```
|
||||||
|
|
||||||
What happened here is we packed all assets required for generating the letter into the ZIP archive, pushed it to the API, waited for it to build a TAR and extracted the resulting files from it.
|
What happened here is we packed all assets required for generating the letter into the ZIP archive, pushed it to the API, waited for it to build a TAR and extracted the resulting files from it.
|
||||||
|
@ -69,3 +69,5 @@ GET /job/{uuid}/download Download the resulting archive (You may specify an
|
||||||
Accept header to select whether to receive a ZIP, a
|
Accept header to select whether to receive a ZIP, a
|
||||||
TAR archive or just the raw PDF.)
|
TAR archive or just the raw PDF.)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
All routes accept the `log-on-error` parameter: If set a PDF download (`Accept` header set to `application/pdf`) will return the log instead of the PDF if no PDF is found.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -109,7 +110,7 @@ func buildAssetsZIP(uid uuid.UUID) (io.Reader, error) {
|
||||||
return buf, errors.Wrap(w.Close(), "closing zip file")
|
return buf, errors.Wrap(w.Close(), "closing zip file")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAssetsPDF(uid uuid.UUID) (io.Reader, error) {
|
func getAssetsFile(uid uuid.UUID, ext string) (io.Reader, error) {
|
||||||
var (
|
var (
|
||||||
buf = new(bytes.Buffer)
|
buf = new(bytes.Buffer)
|
||||||
found bool
|
found bool
|
||||||
|
@ -121,7 +122,7 @@ func getAssetsPDF(uid uuid.UUID) (io.Reader, error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.Ext(info.Name()) != ".pdf" {
|
if path.Ext(info.Name()) != ext {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ func getAssetsPDF(uid uuid.UUID) (io.Reader, error) {
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := osFile.Close(); err != nil {
|
if err := osFile.Close(); err != nil {
|
||||||
logrus.WithError(err).Error("closing output pdf file (leaked fd)")
|
logrus.WithError(err).Error("closing output file (leaked fd)")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ func getAssetsPDF(uid uuid.UUID) (io.Reader, error) {
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
// We found no file
|
// We found no file
|
||||||
return nil, errors.New("no pdf found")
|
return nil, fs.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf, errors.Wrap(err, "walking source dir")
|
return buf, errors.Wrap(err, "walking source dir")
|
||||||
|
|
9
main.go
9
main.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
@ -109,8 +110,14 @@ func downloadAssets(res http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
case "application/pdf":
|
case "application/pdf":
|
||||||
contentType = "application/pdf"
|
contentType = "application/pdf"
|
||||||
content, err = getAssetsPDF(uid)
|
|
||||||
filename = uid.String() + ".pdf"
|
filename = uid.String() + ".pdf"
|
||||||
|
content, err = getAssetsFile(uid, ".pdf")
|
||||||
|
|
||||||
|
if errors.Is(err, fs.ErrNotExist) && r.URL.Query().Has("log-on-error") {
|
||||||
|
contentType = "application/octet-stream"
|
||||||
|
filename = uid.String() + ".log"
|
||||||
|
content, err = getAssetsFile(uid, ".log")
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
content, err = buildAssetsZIP(uid)
|
content, err = buildAssetsZIP(uid)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
@ -133,6 +132,7 @@ func startNewJob(res http.ResponseWriter, r *http.Request) {
|
||||||
go jobProcessor(jobUUID)
|
go jobProcessor(jobUUID)
|
||||||
|
|
||||||
u := urlMust(router.Get("waitForJob").URL("uid", jobUUID.String()))
|
u := urlMust(router.Get("waitForJob").URL("uid", jobUUID.String()))
|
||||||
|
u.RawQuery = r.URL.Query().Encode()
|
||||||
http.Redirect(res, r, u.String(), http.StatusFound)
|
http.Redirect(res, r, u.String(), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,19 +163,30 @@ func waitForJob(res http.ResponseWriter, r *http.Request) {
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
case statusStarted:
|
case statusStarted:
|
||||||
u := urlMust(router.Get("waitForJob").URL("uid", uid.String()))
|
|
||||||
u.RawQuery = url.Values{"loop": []string{strconv.Itoa(loop)}}.Encode()
|
|
||||||
|
|
||||||
<-time.After(time.Duration(math.Pow(sleepBase, float64(loop))) * time.Second)
|
<-time.After(time.Duration(math.Pow(sleepBase, float64(loop))) * time.Second)
|
||||||
|
|
||||||
|
params := r.URL.Query()
|
||||||
|
params.Set("loop", strconv.Itoa(loop))
|
||||||
|
|
||||||
|
u := urlMust(router.Get("waitForJob").URL("uid", uid.String()))
|
||||||
|
u.RawQuery = params.Encode()
|
||||||
|
|
||||||
http.Redirect(res, r, u.String(), http.StatusFound)
|
http.Redirect(res, r, u.String(), http.StatusFound)
|
||||||
return
|
return
|
||||||
|
|
||||||
case statusError:
|
case statusError:
|
||||||
|
if r.URL.Query().Has("log-on-error") {
|
||||||
|
u := urlMust(router.Get("downloadAssets").URL("uid", uid.String()))
|
||||||
|
u.RawQuery = r.URL.Query().Encode()
|
||||||
|
http.Redirect(res, r, u.String(), http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
http.Error(res, "Processing ran into an error.", http.StatusInternalServerError)
|
http.Error(res, "Processing ran into an error.", http.StatusInternalServerError)
|
||||||
|
|
||||||
case statusFinished:
|
case statusFinished:
|
||||||
u := urlMust(router.Get("downloadAssets").URL("uid", uid.String()))
|
u := urlMust(router.Get("downloadAssets").URL("uid", uid.String()))
|
||||||
|
u.RawQuery = r.URL.Query().Encode()
|
||||||
http.Redirect(res, r, u.String(), http.StatusFound)
|
http.Redirect(res, r, u.String(), http.StatusFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue