0

I'm working on an ASP.NET Core Web API that uses PuppeteerSharp to create PDF files from HTML.

It has a Program class:

public partial class Program
{
    public static void Main(string[] callParams)
    {
        new CenterHub().StartWork(callParams);
    }
}

that uses a CenterHub class dealing with setting everything up:

public class CenterHub
{
    public void StartWork(string[] callParams)
    {
        WebApplicationBuilder? appBuilder = WebApplication.CreateBuilder(callParams);

        appBuilder.Services.AddControllersWithViews();

        appBuilder.Services.AddSingleton(new HtmlToPdfService());

        WebApplication? runningApp = appBuilder.Build();

        runningApp.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

        runningApp.Run();
    }
}

Among other things, StartWork() registers a HtmlToPdfService object:

public class HtmlToPdfService
{
    private readonly string[] _puppeteerArgs = new[] {
            "--no-sandbox",
            "--disable-dev-shm-usage",
            "--disable-gpu",
            "--disable-setuid-sandbox",
            "--disable-extensions",
            "--disable-software-rasterizer",
            "--font-render-hinting=none"
        };

    private IBrowser _navigateur { get; }
    private PdfOptions _optionsPdf { get; }

    public HtmlToPdfService()
    {
        BrowserFetcher browserUser = new();
        browserUser.DownloadAsync().GetAwaiter().GetResult();

        _browser = Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true,
            ExecutablePath = "/usr/bin/chromium-browser",
            Args = _puppeteerArgs
        })
            .GetAwaiter()
            .GetResult();

        _pdfOptionSet = new PdfOptions
        {
            Format = PaperFormat.A4,
            PreferCSSPageSize = true,
            PrintBackground = true,
        };
    }
}

All this works fine.

Now, I want to use automated integration tests on the API.

I'm using NUnit. The test class looks like this:

[TestFixture]
internal class TestSpecificDocument1
{
    [Test]
    public async Task TestsRequestForDocument1()
    {
        AppTest appObjectForTest = new();

        Environment.CurrentDirectory = "/app";

        HttpClient clientHttp = appObjectForTest.WithWebHostBuilder(bu => bu.UseEnvironment("Development")).CreateClient();

        // Tests will follow once I get the above code to work
    }
}

It uses the following class to prepare the app for testing:

public class AppTest : WebApplicationFactory<Program>
{

}

(I will provide the appsettings.json file if and when someone asks for it, but until then I feel this question is already long enough.)

However, when running the Puppeteer.LaunchAsync() method from the HtmlToPdfService constructor, I get the following message:

An error occurred trying to start process '/usr/bin/chromium-browser' with working directory 'C:\path_to_my_test_project\bin\Debug\net8.0'.

I've tried variations, such as:

HttpClient clientHttp = appObjectForTest.WithWebHostBuilder(bu => bu.UseStartup<Program>()
                                                                    .UseContentRoot("/app"))
                                        .CreateDefaultClient();

but I still get the same error except the path where Chromium is supposed to be is now C:\app.

EDIT: I forgot to mention that the solution uses Docker Desktop and has a docker-compose project, which accounts for being able to use /usr/bin/chromium-browser on a Windows computer.

How can I make this work? The documentation makes it look very simple, but it doesn't feature running Chromium, nor should it.

13
  • /usr/bin/chromium-browser sounds like *nix but C:\path_to_my_test_project\bin\Debug\net8.0 is going to be Windows. What OS are you using? Commented Sep 27 at 7:07
  • What happens if you leave ExecutablePath as the default? Commented Sep 27 at 7:09
  • @phuzi: I work on a Windows PC, but the API is deployed on a Linux server. As for ExecutablePath, I seem to remember it comes from the PuppeteerSharp documentation. I'll look into it. Commented Sep 29 at 7:11
  • 2
    /usr/bin/chromium-browser just plain old won't work on Windows. If you need different paths for different systems/environments you could do worse than sticking the path in config which could be overwritten by an environment variable. Commented Sep 29 at 8:18
  • 1
    Your main concern is this: en.wikipedia.org/wiki/Principle_of_least_privilege You still haven't said what the purpose is here (is this running on production server?)... but in addition to giving your server-side code privileges to launch executables outside of your web directories, you are also poking holes in the browser sandbox when you launch a browser in dev-mode. Commented Sep 30 at 18:11

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.