diff --git a/go.mod b/go.mod index 9222beb..6af822d 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,12 @@ require ( github.com/gin-gonic/gin v1.9.1 ) +require github.com/google/uuid v1.4.0 + require ( github.com/aws/aws-sdk-go-v2 v1.22.2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0 // indirect - github.com/aws/aws-sdk-go-v2/config v1.23.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.23.0 github.com/aws/aws-sdk-go-v2/credentials v1.15.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.3 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.2 // indirect diff --git a/go.sum b/go.sum index cd92ef7..041a796 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= diff --git a/grender.yaml b/grender.yaml index 90032ef..b347c53 100644 --- a/grender.yaml +++ b/grender.yaml @@ -1,18 +1,18 @@ version: v1 renderingConfig: - pageWaitTime: 5 + pageWaitTime: 10 pageWaitCondition: '(function() { return window.prerenderReady === true })()' - requestHeaders: - - name: "X-Grender-Request" - value: "1" + # requestHeaders: + # - name: "X-Grender-Request" + # value: "1" server: - port: "8080" - headers: + port: "8081" + responseHeaders: - name: "X-Prerender" value: "1" backend: - fileSystem: - baseDir: "./tmp" + # fileSystem: + # baseDir: "./tmp" s3: bucketName: "grender.io" region: "ap-southeast-2" diff --git a/pilot/handler_render.go b/pilot/handler_render.go new file mode 100644 index 0000000..3f739bd --- /dev/null +++ b/pilot/handler_render.go @@ -0,0 +1,54 @@ +package pilot + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/krishanthisera/grender/backend" +) + +// Rendering handler +func (C *Config) renderHandler(ctx *gin.Context) { + url := ctx.Param("url") + fmt.Println(url) + + var be backend.Backend + var err error + + // Check S3 backend configuration + if s3 := C.Backend.S3; s3.BucketName != "" { + be, err = createBackendFromConfig(s3) + } else if fs := C.Backend.FileSystem; fs.BaseDir != "" { + // Check FileSystem backend configuration + be, err = createBackendFromConfig(fs) + } else { + // No backend found + fmt.Println("No backend found") + } + + if err != nil { + fmt.Println(err) + ctx.String(http.StatusInternalServerError, "Error creating backend: %v", err) + return + } + rac := renderAndCacheConfig{backend: &be, render: &C.RenderingConfig} + renderedHTML, err := rac.RenderAndCache(url) + + // Page is rendered successfully + if renderedHTML != nil { + // Setting required headers + C.addResponseHeaders(ctx) + ctx.Data(http.StatusOK, "text/html", []byte(renderedHTML)) + + // Page cannot be cached + if err != nil { + ctx.String(http.StatusInternalServerError, "Error caching URL: %v", err) + return + } + return + } + + // Page cannot be rendered + ctx.String(http.StatusInternalServerError, "Error rendering URL: %v", err) +} diff --git a/pilot/models.go b/pilot/models.go index a394bba..d1973e3 100644 --- a/pilot/models.go +++ b/pilot/models.go @@ -7,15 +7,19 @@ import ( // Config struct to represent the overall YAML configuration type Config struct { - Version string `yaml:"version"` - RenderingConfig render.Config `yaml:"renderingConfig"` + Version string `yaml:"version" required:"true"` + RenderingConfig render.Config `yaml:"renderingConfig" required:"true"` Server struct { - Port string `yaml:"port"` - } `yaml:"server"` + Port string `yaml:"port" required:"true"` + ResponseHeaders []struct { + Name string `yaml:"name"` + Value string `yaml:"value"` + } `yaml:"responseHeaders"` + } `yaml:"server" required:"true"` Backend struct { S3 backend.S3 `yaml:"s3"` FileSystem backend.FileSystem `yaml:"fileSystem"` - } `yaml:"backend"` + } `yaml:"backend" required:"true"` } type renderAndCacheConfig struct { diff --git a/pilot/pilot.go b/pilot/pilot.go index 7d29b9c..6391990 100644 --- a/pilot/pilot.go +++ b/pilot/pilot.go @@ -2,7 +2,6 @@ package pilot import ( "fmt" - "net/http" "github.com/gin-gonic/gin" ) @@ -10,33 +9,10 @@ import ( func (C *Config) Grender() { router := gin.Default() - router.GET("/render/*url", func(c *gin.Context) { - url := c.Param("url") - fmt.Println(url) - be, err := createBackendFromConfig(C.Backend.S3) - if err != nil { - fmt.Println(err) - } - rac := renderAndCacheConfig{backend: &be, render: &C.RenderingConfig} - renderedHTML, err := rac.RenderAndCache(url) - - // Page is rendered successfully - if renderedHTML != nil { - c.Data(http.StatusOK, "text/html", []byte(renderedHTML)) - // Page cannot be cached - if err != nil { - c.String(http.StatusInternalServerError, "Error caching URL: %v", err) - return - } - return - } else { - // Page cannot be rendered - c.String(http.StatusInternalServerError, "Error rendering URL: %v", err) - return - } - - }) + // Rendering requests + router.GET("/render/*url", C.renderHandler) + router.HEAD("/render/*url", C.renderHandler) router.Run(fmt.Sprintf(":%s", C.Server.Port)) } diff --git a/pilot/utils.go b/pilot/utils.go index 4e1b316..84c8bbd 100644 --- a/pilot/utils.go +++ b/pilot/utils.go @@ -7,6 +7,7 @@ import ( aws "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/gin-gonic/gin" "github.com/krishanthisera/grender/backend" "gopkg.in/yaml.v2" ) @@ -26,6 +27,12 @@ func createBackendFromConfig(backendConfig interface{}) (backend.Backend, error) } } +func (C *Config) addResponseHeaders(ctx *gin.Context) { + for _, h := range C.Server.ResponseHeaders { + ctx.Header(h.Name, h.Value) + } +} + // TO DO: Refactor this to use the backend package // func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { // var buf map[string]interface{} diff --git a/render/render.go b/render/render.go index 5ba02e8..37b697b 100644 --- a/render/render.go +++ b/render/render.go @@ -11,7 +11,6 @@ import ( "github.com/chromedp/cdproto/dom" "github.com/chromedp/cdproto/network" "github.com/chromedp/chromedp" - "github.com/google/uuid" ) func (config Config) Render(webAddr string) (*string, error) { @@ -36,32 +35,28 @@ func (config Config) Render(webAddr string) (*string, error) { var html string // Set request headers - headers := func() network.Headers { - h := network.Headers{"X-Grender-Request-Id": fmt.Sprintf("%v", uuid.New())} - for _, v := range config.RequestHeaders { - h[v.Name] = v.Value - } - fmt.Println(h) - return h - }() + headers := map[string]interface{}{ + "Grerender-Request-Id": "my request header", + } - if err := chromedp.Run(ctx, pageRender(webAddr, config.PageWailCondition, time.Duration(config.PageWaitTime*float32(time.Second)), &headers, &html)); err != nil { + if err := chromedp.Run(ctx, pageRender(webAddr, config.PageWailCondition, time.Duration(config.PageWaitTime*float32(time.Second)), headers, &html)); err != nil { return nil, err } return &html, nil } // This is the function that does the actual rendering -func pageRender(webAddr string, waitCondition string, pageWaitTime time.Duration, headers *network.Headers, html *string) chromedp.Tasks { +func pageRender(webAddr string, pageWaitCondition string, pageWaitTime time.Duration, headers network.Headers, html *string) chromedp.Tasks { return chromedp.Tasks{ network.Enable(), - network.SetExtraHTTPHeaders(*headers), + // Setting the netowrk headers has been disable as: ..."net::ERR_FAILED","canceled":false,"corsErrorStatus":{"corsError":"HeaderDisallowedByPreflightResponse","failedParameter":"grerender-request-id"}} + // network.SetExtraHTTPHeaders(network.Headers(headers)), chromedp.Navigate(webAddr), chromedp.ActionFunc(func(ctx context.Context) error { var result bool startTime := time.Now() for time.Since(startTime) < pageWaitTime { - if err := chromedp.Evaluate(waitCondition, &result).Do(ctx); err != nil { + if err := chromedp.Evaluate(pageWaitCondition, &result).Do(ctx); err != nil { return err } if result {