── Rendering ─────────────────────────────────────────────────────── renderPageHTML navigates a headless browser to target and returns the rendered DOM serialized as HTML. target must already have passed validateWebTarget. The whole operation is bounded by webRenderTimeout.
(ctx context.Context, target string)
| 302 | // rendered DOM serialized as HTML. target must already have passed |
| 303 | // validateWebTarget. The whole operation is bounded by webRenderTimeout. |
| 304 | func renderPageHTML(ctx context.Context, target string) (string, error) { |
| 305 | browser, err := renderShared.acquire() |
| 306 | if err != nil { |
| 307 | return "", err |
| 308 | } |
| 309 | |
| 310 | rctx, cancel := context.WithTimeout(ctx, webRenderTimeout()) |
| 311 | defer cancel() |
| 312 | |
| 313 | // Per-render incognito context: cookies, storage and cache are never |
| 314 | // shared between unrelated target sites within the same session. |
| 315 | inc, err := browser.Incognito() |
| 316 | if err != nil { |
| 317 | return "", fmt.Errorf("creating isolated browser context: %w", err) |
| 318 | } |
| 319 | page, err := inc.Page(proto.TargetCreateTarget{}) |
| 320 | if err != nil { |
| 321 | return "", fmt.Errorf("opening page: %w", err) |
| 322 | } |
| 323 | page = page.Context(rctx) |
| 324 | defer func() { _ = page.Close() }() |
| 325 | |
| 326 | if err := preparePage(page); err != nil { |
| 327 | return "", err |
| 328 | } |
| 329 | return navigateAndSerialize(page, target) |
| 330 | } |
| 331 | |
| 332 | // preparePage applies the UA override and installs the SSRF hijack before |
| 333 | // any navigation happens. |