Files
Jonathan Ingram 93312f47fc v2: initial commit (#153)
- Some methods have been changed to return an error as their last
  argument
- Log calls inside various functions have been removed
- Use a v1 tag if you need the previous signature
2023-10-31 11:32:40 +11:00

136 lines
4.7 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"runtime"
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/errorreporting"
"github.com/gorilla/mux"
"code.sajari.com/docconv/v2"
"code.sajari.com/docconv/v2/docd/internal"
"code.sajari.com/docconv/v2/docd/internal/cloudtrace"
"code.sajari.com/docconv/v2/docd/internal/debug"
)
var (
listenAddr = flag.String("addr", ":8888", "The address to listen on (e.g. 127.0.0.1:8888)")
inputPath = flag.String("input", "", "The file path to convert and exit; no server")
jsonCloudLogging = flag.Bool("json-cloud-logging", false, "Whether or not to enable JSON Cloud Logging")
cloudTraceGCPProjectID = flag.String("cloud-trace-gcp-project-id", "", "The GCP project to use for Cloud Trace")
errorReporting = flag.Bool("error-reporting", false, "Whether or not to enable GCP Error Reporting")
errorReportingGCPProjectID = flag.String("error-reporting-gcp-project-id", "", "The GCP project to use for Error Reporting")
errorReportingAppEngineService = flag.String("error-reporting-app-engine-service", "", "The App Engine service to use for Error Reporting")
readabilityLengthLow = flag.Int("readability-length-low", 70, "Sets the readability length low")
readabilityLengthHigh = flag.Int("readability-length-high", 200, "Sets the readability length high")
readabilityStopwordsLow = flag.Float64("readability-stopwords-low", 0.2, "Sets the readability stopwords low")
readabilityStopwordsHigh = flag.Float64("readability-stopwords-high", 0.3, "Sets the readability stopwords high")
readabilityMaxLinkDensity = flag.Float64("readability-max-link-density", 0.2, "Sets the readability max link density")
readabilityMaxHeadingDistance = flag.Int("readability-max-heading-distance", 200, "Sets the readability max heading distance")
readabilityUseClasses = flag.String("readability-use-classes", "good,neargood", "Comma separated list of readability classes to use")
)
func main() {
flag.Parse()
l := slog.New(debug.NewDebugHandler(slog.Default().Handler()))
if *jsonCloudLogging {
gcpProjectID := *cloudTraceGCPProjectID
if gcpProjectID == "" {
gcpProjectID = os.Getenv("GOOGLE_CLOUD_PROJECT")
}
if gcpProjectID == "" {
l.Debug("GOOGLE_CLOUD_PROJECT env var not provided, looking up internal metadata service")
var err error
gcpProjectID, err = metadata.ProjectID()
if err != nil {
l.Error("Could not autodetect GCP project ID", "error", err)
os.Exit(1)
}
}
l = slog.New(debug.NewDebugHandler(cloudtrace.NewCloudLoggingHandler(gcpProjectID, slog.LevelInfo)))
slog.SetDefault(l)
l.Info("Cloud Trace GCP project ID", "projectID", gcpProjectID)
}
var er internal.ErrorReporter = &internal.NopErrorReporter{}
if *errorReporting {
if *errorReportingGCPProjectID == "" {
*errorReportingGCPProjectID = os.Getenv("GOOGLE_CLOUD_PROJECT")
}
if *errorReportingAppEngineService == "" {
*errorReportingAppEngineService = os.Getenv("GAE_SERVICE")
}
var err error
er, err = errorreporting.NewClient(context.Background(), *errorReportingGCPProjectID, errorreporting.Config{
ServiceName: *errorReportingAppEngineService,
OnError: func(err error) {
l.Error("Could not report error to Error Reporting service", "error", err)
},
})
if err != nil {
l.Error("Could not create Error Reporting client", "error", err)
os.Exit(1)
}
}
cs := &convertServer{
l: l,
er: er,
}
// TODO: Improve this (remove the need for it!)
docconv.HTMLReadabilityOptionsValues = docconv.HTMLReadabilityOptions{
LengthLow: *readabilityLengthLow,
LengthHigh: *readabilityLengthHigh,
StopwordsLow: *readabilityStopwordsLow,
StopwordsHigh: *readabilityStopwordsHigh,
MaxLinkDensity: *readabilityMaxLinkDensity,
MaxHeadingDistance: *readabilityMaxHeadingDistance,
ReadabilityUseClasses: *readabilityUseClasses,
}
if *inputPath != "" {
resp, err := docconv.ConvertPath(*inputPath)
if err != nil {
l.Error("Could not convert file", "error", err, "path", *inputPath)
os.Exit(1)
}
fmt.Print(string(resp.Body))
return
}
serve(l, er, cs)
}
// Start the conversion web service
func serve(l *slog.Logger, er internal.ErrorReporter, cs *convertServer) {
r := mux.NewRouter()
r.HandleFunc("/convert", cs.convert)
h := internal.RecoveryHandler(l, er)(r)
h = &debug.HTTPHandler{Handler: h}
h = &cloudtrace.HTTPHandler{Handler: h}
l.Info("Go version " + runtime.Version())
l.Info(fmt.Sprintf("HTTP server listening on %q...", *listenAddr))
if err := http.ListenAndServe(*listenAddr, h); err != nil {
l.Error("HTTP server ListenAndServe", "error", err)
}
}