github.com/raphaelreyna/latte@v0.11.2-0.20220317193248-98e2fcef4eef/internal/server/generate-route.go (about)

     1  package server
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/raphaelreyna/go-recon/sources"
    11  	"github.com/raphaelreyna/latte/internal/job"
    12  )
    13  
    14  func (s *Server) handleGenerate() http.HandlerFunc {
    15  	type errorResponse struct {
    16  		Error string `json:"error"`
    17  		Data  string `json:"data,omitempty"`
    18  	}
    19  
    20  	return func(w http.ResponseWriter, r *http.Request) {
    21  		// Create temporary directory into which we'll copy all of the required resource files
    22  		// and eventually run pdflatex in.
    23  		workDir, err := ioutil.TempDir(s.rootDir, "")
    24  		if err != nil {
    25  			s.errLog.Println(err)
    26  			http.Error(w, err.Error(), http.StatusInternalServerError)
    27  			return
    28  		}
    29  		s.infoLog.Printf("created new temp directory: %s", workDir)
    30  		defer func() {
    31  			go func() {
    32  				if err = os.RemoveAll(workDir); err != nil {
    33  					s.errLog.Println(err)
    34  				}
    35  			}()
    36  		}()
    37  
    38  		// Create a new job for this request
    39  		j := job.NewJob(workDir, sources.NewDirSourceChain(sources.SoftLink, s.rootDir))
    40  		if s.db != nil {
    41  			j.SourceChain = append(j.SourceChain, s.db)
    42  		}
    43  
    44  		// Grab any data sent as JSON
    45  		if r.Header.Get("Content-Type") == "application/json" {
    46  			var req job.Request
    47  			defer r.Body.Close()
    48  			if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    49  				s.errLog.Println(err)
    50  				http.Error(w, err.Error(), http.StatusInternalServerError)
    51  				return
    52  			}
    53  
    54  			// Grab details if they were provided
    55  			if j, err = req.NewJob(workDir, j.SourceChain, s.tmplCache); err != nil {
    56  				s.errLog.Println(err)
    57  				http.Error(w, err.Error(), http.StatusBadRequest)
    58  				return
    59  			}
    60  		}
    61  
    62  		// Check the url quuery values for a registered template, registered details or resources
    63  		// as well as for compilation options and modify the Job accordingly.
    64  		if err = j.ParseQuery(r.URL.Query(), s.tmplCache); err != nil {
    65  			s.errLog.Println(err)
    66  			http.Error(w, err.Error(), http.StatusBadRequest)
    67  			return
    68  		}
    69  
    70  		// Compile pdf
    71  		pdfPath, err := j.Compile(r.Context())
    72  		if err != nil {
    73  			er := &errorResponse{Error: err.Error(), Data: string(pdfPath)}
    74  			w.Header().Set("Content-Type", "application/json")
    75  			s.errLog.Printf("%s", s.respond(w, er, http.StatusInternalServerError))
    76  			return
    77  		}
    78  
    79  		// Send the newly rendered PDF to the client
    80  		w.Header().Set("Content-Type", "application/pdf")
    81  		http.ServeFile(w, r, filepath.Join(workDir, pdfPath))
    82  	}
    83  }