package services import ( "bytes" "fmt" "mime/multipart" "net/http" "strconv" "github.com/oxplot/papersizes" "go.uber.org/zap" ) type Converter interface { ToPdf(html string, pageSize string, landscape bool) ([]byte, error) } type GotenbergConverter struct { BaseUrl string Logger *zap.SugaredLogger } func (g *GotenbergConverter) ToPdf(html string, pageSize string, landscape bool) ([]byte, error) { logger := g.Logger.Named("ToPdf").With("page_size", pageSize, "landscape", landscape, "base_url", g.BaseUrl) client := &http.Client{} defer client.CloseIdleConnections() logger.Debug("Created HTTP client") body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("files", "index.html") if err != nil { logger.Errorw("Failed to create form file", "error", err) return nil, err } _, err = part.Write([]byte(html)) if err != nil { logger.Errorw("Failed to write to form file", "error", err) return nil, err } size := papersizes.FromName(pageSize) if size == nil { logger.Errorw("Invalid page size", "size", pageSize) return nil, fmt.Errorf("invalid page size: %s", pageSize) } err = writer.WriteField("paperWidth", strconv.Itoa(size.Width)+"mm") if err != nil { logger.Errorw("Failed to write paper width", "error", err) return nil, err } err = writer.WriteField("paperHeight", strconv.Itoa(size.Height)+"mm") if err != nil { logger.Errorw("Failed to write paper height", "error", err) return nil, err } err = writer.WriteField("landscape", strconv.FormatBool(landscape)) if err != nil { logger.Errorw("Failed to write landscape", "error", err) return nil, err } err = writer.WriteField("marginTop", "0") if err != nil { logger.Errorw("Failed to write margin top", "error", err) return nil, err } err = writer.WriteField("marginBottom", "0") if err != nil { logger.Errorw("Failed to write margin bottom", "error", err) return nil, err } err = writer.WriteField("marginLeft", "0") if err != nil { logger.Errorw("Failed to write margin left", "error", err) return nil, err } err = writer.WriteField("marginRight", "0") if err != nil { logger.Errorw("Failed to write margin right", "error", err) return nil, err } err = writer.WriteField("preferCssPageSize", "true") if err != nil { logger.Errorw("Failed to write prefer css page size", "error", err) return nil, err } err = writer.Close() if err != nil { logger.Errorw("Failed to close writer", "error", err) return nil, err } logger.Debug("Created form data") logger.Debug("Creating HTTP request") req, err := http.NewRequest("POST", g.BaseUrl+"/forms/chromium/convert/html", body) if err != nil { return nil, err } req.Header.Set("Content-Type", writer.FormDataContentType()) logger.Debug("Sending HTTP request") resp, err := client.Do(req) if err != nil { logger.Errorw("Failed to send request", "error", err) return nil, err } logger.Debug("Received HTTP response") defer resp.Body.Close() data := new(bytes.Buffer) _, err = data.ReadFrom(resp.Body) if err != nil { logger.Errorw("Failed to read response body", "error", err) return nil, err } logger.Debug("Returning PDF data") return data.Bytes(), nil }