Files
gotenberg/app/handlers/handlers.go
Julien Neuhart e847c86baa huge refactoring
2018-03-29 20:13:19 +02:00

127 lines
3.2 KiB
Go

package handlers
import (
"fmt"
"io"
"net/http"
"os"
"github.com/gulien/gotenberg/app/handlers/context"
"github.com/gulien/gotenberg/app/handlers/converter"
ghttp "github.com/gulien/gotenberg/app/handlers/http"
"github.com/gulien/gotenberg/app/logger"
"github.com/justinas/alice"
)
func GetHandlersChain() http.Handler {
return alice.New(enforceContentLengthHandler, enforceContentTypeHandler, convertHandler, serveHandler).ThenFunc(clearHandler)
}
// enforeContentLengthHandler checks if the request has content.
func enforceContentLengthHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.ContentLength == 0 {
e := &requestHasNoContentError{}
http.Error(w, e.Error(), http.StatusBadRequest)
logger.Error(e)
return
}
next.ServeHTTP(w, r)
})
}
// enforceContentTypeHandler checks if the "Content-Type" entry
// from the request's header matches one of the allowed content types.
func enforceContentTypeHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ct, err := ghttp.FindAuthorizedContentType(r.Header)
if err != nil {
http.Error(w, err.Error(), http.StatusUnsupportedMediaType)
logger.Error(err)
return
}
r = context.WithContentType(r, ct)
next.ServeHTTP(w, r)
})
}
// convertHandler is in charge of converting the file(s) from the request to PDF.
func convertHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ct, err := context.GetContentType(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
return
}
c, err := converter.NewConverter(r, ct)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
return
}
err = c.Convert()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
return
}
r = context.WithConverter(r, c)
next.ServeHTTP(w, r)
})
}
// serveHandler simply serves the created PDF.
func serveHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c, err := context.GetConverter(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
}
reader, err := os.Open(c.FinalFilePath)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
return
}
defer reader.Close()
resultFileInfo, err := reader.Stat()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
logger.Error(err)
return
}
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", resultFileInfo.Name()))
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Length", fmt.Sprintf("%d", resultFileInfo.Size()))
io.Copy(w, reader)
next.ServeHTTP(w, r)
})
}
// clearHandler removes all files created during the conversion.
func clearHandler(w http.ResponseWriter, r *http.Request) {
c, err := context.GetConverter(r)
if err != nil {
logger.Warn(err.Error())
}
if err := c.Clear(); err != nil {
logger.Warn(err.Error())
}
}