Headless Chrome will not load css files unless the client is the same machine as the webserver

239 views Asked by At

We are generating PDF using headless chrome with puppeteer sharp. This has been working fine until one day it stopped loading the css files and our PDFs were missing all their bootstrap styles.

Recent events:
on the 16th we upgraded to .NET 8
on the 28th the PDF was reported as broken (our billing team uses this pdf generator every day)
We didn't change anything with regards to the pdf generations process

Below is the code I use to generate the PDF using puppeteer sharp.

public async Task<byte[]> GetPdf(Controller controller, string view, object model, string pdfName, string? headerHtml = null, string? footerHtml = null)
        {
            using (var browserFetcher = new BrowserFetcher())
            {
                await browserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId);

                using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions
                {
                    Headless = true
                }))
                {
                    if (string.IsNullOrWhiteSpace(footerHtml))
                    {
                        footerHtml = await this.RenderView(controller, "_ReportFooter", "");
                    }

                    PdfOptions pdfOptions = new PdfOptions()
                    {
                        DisplayHeaderFooter = true,
                        FooterTemplate = footerHtml,
                        HeaderTemplate = headerHtml ?? "<span></span>",
                        PrintBackground = true,
                        Format = PaperFormat.A4,
                        MarginOptions =
                                        {
                                            Top = "20px",
                                            Bottom = "60px",
                                            Left = "40px",
                                            Right = "40px"
                                        }
                    };


                    using (var page = await browser.NewPageAsync())
                    {
                        //await page.GoToAsync("https://***domainName***/Workorders/ViewWorkorderPDF?workorderIdsAsString=239379", new NavigationOptions
                        //{
                        //    WaitUntil = [WaitUntilNavigation.Load, WaitUntilNavigation.DOMContentLoaded, WaitUntilNavigation.Networkidle0, WaitUntilNavigation.Networkidle2]
                        //});
                        //await page.SetContentAsync(await RenderView(controller, view, model, true), new NavigationOptions { Timeout = 60000, WaitUntil = [WaitUntilNavigation.Load, WaitUntilNavigation.DOMContentLoaded, WaitUntilNavigation.Networkidle0, WaitUntilNavigation.Networkidle2] });
                        await page.SetContentAsync(await RenderView(controller, view, model, true), new NavigationOptions { WaitUntil = [WaitUntilNavigation.Load, WaitUntilNavigation.Networkidle0] });
                        await page.WaitForNavigationAsync();
                        var toReturn = await page.PdfDataAsync(pdfOptions);
                        await browser.CloseAsync();

                        return toReturn;
                    }
                }
            }

This is an example of the views I am using to generate the html. NOTE: @host is replaced with our hostname

<html>
<head>
    <meta charset="utf-8">
    <base href="https://@host/">
    @*<link href="https://@host/lib/WorkordersPrintable-BootStrap/css/bootstrap.min.css" rel="stylesheet" asp-append-version="true" />*@
    <link href="https://@host/lib/bootstrap-3.4.1-dist/css/bootstrap.min.css" rel="stylesheet" asp-append-version="true" />
    <link href="https://@host/css/WorkordersPrintable.css" rel="stylesheet" asp-append-version="true" />
    @*<link href="https://@host/css/WorkordersPrintableMedia.css" rel="stylesheet" asp-append-version="true" />*@
</head>
<body>
    <div class="container PrintView">
        <div class="row">
            @if (Model.BulkSummary != null && Model.BulkSummary.Count() > 0)
            {
                <div class="col-12">
                    <div class="d-flex justify-content-center">
                        @if (Model.CompanyName != null)
                        {
                            <h3>@Model.CompanyName - Bulk Report</h3>
                        }
                        <h3>@Model.StartDate - @Model.EndDate</h3>
                    </div>
                </div>
....

Below is some PDF examples of the working and not working PDFs. I blacked out confidential information

Client is the webserver: enter image description here

Client is any other computer: enter image description here

This works fine every time in our development environment. This prompted me to try generating the PDF by navigating to the generator on the webserver hosting the web application and it worked completely fine if I used a browser on the webserver. This leads me to believe it could be some sort of networking change or a change to the installed chrome so I updated the webserver (running windows server 2016)

1

There are 1 answers

0
BoMerican On

This started working as soon as I set headless to false and published to beta which runs on the same webserver but is a different build that I use so that I don't constantly bring down production for a publish. When I ran the browser as headless = false on beta it worked on production with no changes to that build. I don't know if this is a coincidence or if this is the solution. I spoke with my ops team and they were not making any changes at the time. I would welcome any explanation if someone knows more about what is going on here.

I will add updates if this happens again.