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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.