Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Azure #383

Closed
raupes opened this issue Jul 9, 2018 · 32 comments
Closed

Support for Azure #383

raupes opened this issue Jul 9, 2018 · 32 comments
Labels
feature Unplanned Not part of the actual roadmap

Comments

@raupes
Copy link

raupes commented Jul 9, 2018

Description

Trying hole day. Is it possible to run on Azure App Service?
Also when trying to copy installation result from npm install puppeteer to output I still get the error
Win32Exception: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail
at this line
PuppeteerSharp.Launcher.LaunchAsync(LaunchOptions options)
And I simply can't install chrome there.

Hope you can help or be able how to get this cool project running on azure.

thank you

Complete minimal example reproducing the issue

      public class HomeController : Controller
{
    string path;
    public HomeController(IHostingEnvironment hostingEnvironment) {
        this.path = hostingEnvironment.ContentRootPath;
    }
    public async Task<IActionResult> Index()
    {
        bool exist = false;
        using(var browser = await PuppeteerSharp.Puppeteer.LaunchAsync(new LaunchOptions() {
            Headless = true,
            ExecutablePath = this.path + @"\node_modules\puppeteer\.local-chromium\win64-564778\chrome-win32\chrome.exe"
        })) {
            using(var page =await browser.NewPageAsync()) {
                var response = await page.GoToAsync("http://www.sales-suckers.com");
                var res = await page.EvaluateExpressionAsync<dynamic>("window.salessuckers");
                exist = res != null;
            }
        }
        ViewData.Add("EXIST", exist);
        return View();
    }

}

Expected behavior:

Please add description how to run within Azure App Service or add support to it.

Versions

  • Which version of PuppeteerSharp are you using? 1.1
  • Which .NET runtime and version are you targeting? .NET Core 2.0. .NET Core 2.1
@kblok
Copy link
Member

kblok commented Jul 9, 2018

You won't be able to run chrome on Azure, you'll have to use an external chrome process. I wrote a post about this http://www.hardkoded.com/blogs/azure-chrome-puppeteer-browserless

@raupes
Copy link
Author

raupes commented Jul 9, 2018

Too bad.
Thanks I need to think about it using browserless - or probably i found an other service for a couple of requests.

thanks!

@raupes raupes closed this as completed Jul 9, 2018
@brightertools
Copy link

When you say it won't work in Azure, will Puppeteer-Sharp not run within a .net core web application? Or are talking about Azure Functions, or both?

@kblok
Copy link
Member

kblok commented Oct 16, 2018

@brightertools I didn't have the time to test it again.
It's not a Puppeteer's limitation. It is an environment limitation. The WebApp or Azure Function should be able to run Chromium and Chromium should have all the CGI components it needs to run.

If you can test it and let us know how it went it would be great.

@brightertools
Copy link

@kblok : ok, I just found your project today so am a little early in terms of deploying anything just yet, but will need to test that to make sure what we are doing works...

@kblok
Copy link
Member

kblok commented Oct 16, 2018

@brightertools cool, Let us know how it goes.

@PradeepLoganathan
Copy link

PradeepLoganathan commented Oct 17, 2018

I tried to run it in an azure web app and it fails. This is my code

              var options = new LaunchOptions
                {
                    Headless = true
                };

                await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

                
                using (var browser = await Puppeteer.LaunchAsync(options))
                using (var page = await browser.NewPageAsync())
                {
                    await page.GoToAsync(htmlurl);
                    document = await page.PdfStreamAsync();
                }

                return document;

It fails on this line using (var browser = await Puppeteer.LaunchAsync(options)) and I
don't even get an exception. The call fails with a 502 invalid gateway error. I was hopeful of
using this to generate pdf's :-)

@kblok
Copy link
Member

kblok commented Oct 17, 2018

@PradeepLoganathan is that a WebApp?

@drsasankh
Copy link

drsasankh commented Nov 26, 2018

I have the same issue
Mine is a web app

@ravtakhar
Copy link

ravtakhar commented Jan 19, 2019

Same issue here can't run it on my web app

EDIT: Just spent all morning implementing this to replace 'SelectPDF' and it failed upon deployment. Also using a web app and tried to copy across chrome files manually still no luck.

@ravtakhar
Copy link

@kblok are you planning on looking into this? SelectPDF is working fine, but slow and far more limited than this library.

@kblok
Copy link
Member

kblok commented Feb 27, 2019

@ravtakhar I don't think I will be able to dig into this in the following 30 days.

@ravtakhar
Copy link

@kblok wondering if we can open this issue again. I tried to take a look, but I think it's a little too over my head.

@kblok
Copy link
Member

kblok commented Mar 28, 2019

@ravtakhar reopened

@kblok kblok reopened this Mar 28, 2019
@kblok kblok added feature Unplanned Not part of the actual roadmap labels Mar 28, 2019
@rytmis
Copy link

rytmis commented Apr 19, 2019

I got a little bit further, but still no success.

My code is:

    public class PuppeteerRenderer : IPdfRenderer {
        public async Task<byte[]> RenderPdfAsync(string htmlInput)
        {
            var fetcher = new BrowserFetcher(new BrowserFetcherOptions()
            {
                Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Puppeteer")
            });

            await fetcher.DownloadAsync(BrowserFetcher.DefaultRevision);

            var path = fetcher.GetExecutablePath(BrowserFetcher.DefaultRevision);
            
            var options = new LaunchOptions()
            {
                Headless = true,
                ExecutablePath = path
            };

            using (var browser = await Puppeteer.LaunchAsync(options))
            {
                var page = await browser.NewPageAsync();
                await page.SetContentAsync(htmlInput);
                return await page.PdfDataAsync();
            }
        }
    }

The only interesting part is the one where I specify the folder for the Chromium download. When attempting this with MVC 5 running locally on IIS Express, I noticed that the default working directory is one where the app can't write, so specifying this helped.

In Azure App Service, though, execution hangs at await browser.NewPageAsync(); (checked via remote debugging) and eventually the result is a 502. I can see that the Chrome process gets launched, but nothing more than that.

image

@CREFaulk
Copy link

CREFaulk commented May 9, 2019

BrowserFetcher uses Directory.GetCurrentDirectory() to download to but if you are running PuppeteerSharp in a service it'll be something like "C:\Windows\System32".

I added a statement to when my service was starting and gave the service user permissions on the install folder:
System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);

@WernerMairl
Copy link

May be this is a idea to solve this:

https://oren.codes/2018/02/25/registration-free-com-with-azure-app-services/

@mikecabana
Copy link

Status update? Is this a viable feature?

@brightertools
Copy link

We are using PuppeteerSharp in Azure (AppService) with the browserless.io service and it works well.

I followed @kblok 's example here: http://www.hardkoded.com/blogs/azure-chrome-puppeteer-browserless

@kblok
Copy link
Member

kblok commented Aug 16, 2019

Are you looking for something like this?
image

Blog post is coming :)

@lohithdhanakonda
Copy link

I am deploying my application on azure, seems I cannot use BrowserFetcher. (In local anyhow I am using this, sometimes chrome.exe from Program files)
Is there any chance, that we could use chrome.exe file path as the executable path, from the machine, where we have deployed the application. Actually, I don't want to use the remote browser. Instead, can I use the .exe path directly, in Azure?

@GFoley83
Copy link

GFoley83 commented Sep 9, 2019

Can confirm that it's currently not possible to run Puppeteer on Azure Functions either. You get the same error as raupes:

System.Private.CoreLib: Exception while executing function: WebPageScanJob. System.Diagnostics.Process: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

image

Which gets triggered as soon as you call:

var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = true
});

Looks like it's a known issue: Azure/azure-functions-host/issues/2417

@kblok
Copy link
Member

kblok commented Sep 13, 2019

I wrote about a possible solution here http://www.hardkoded.com/blog/running-puppeteer-sharp-azure-functions

@kblok kblok closed this as completed Sep 13, 2019
@daiplusplus
Copy link

daiplusplus commented Sep 27, 2019

@kblok Kinda a cop-out to use a Linux Docker image rather than running in-place within an Azure App Service or Azure Function.

FWIW, I'm able to work-around (fix?) the winsxs issue by running chrome.exe from the "real" path (not the virtualized D:\home\... path), but then the chrome.exe process never quits - I haven't done any further investigation, but the fact that Chrome.exe is able to start and connect with Puppeteer is encouraging (also it's 4:31am where I am as I write this - so I hope you'll forgive me for not delving deeper).

I first posted my semi-solution to here ( Azure/azure-functions-host#2417 ) but I've replicated it here:


I was able to get chrome.exe to run by working-around the side-by-side error by running from the HOME_EXPANDED directory - I do get some assortment of errors written out of stderr and stdout but at least it does run.

For those wondering, do this:

  1. Open Kudu's cmd prompt in your D:\home directory.
  2. echo %HOME_EXPANDED% (this will print a C:\... path)
  3. cd %HOME_EXPANDED% (nothing will happen, but do it anyway)
  4. c: (this will put you in your "real" home directory)
  5. site\your-chome-directory\chrome.exe
  6. It is now running - you'll see some stderr and/or stdout messages printed too. Unfortunately as Kudu doesn't forward Ctrl+C (or has any means of killing processes, really) you can't do anything and will need to open a new Kudu window to start again - but it shows that Chrome.exe can be made to start.

This is the stderr output I get in Kudu:

[0927/113701.658:ERROR:handler_main.cc(961)] SetProcessShutdownParameters: The parameter is incorrect. (0x57)
[0927/113701.670:ERROR:handler_main.cc(961)] SetProcessShutdownParameters: The parameter is incorrect. (0x57)
[7780:5424:0927/113703.310:ERROR:network_change_notifier_win.cc(141)] WSALookupServiceBegin failed with: 203
[0927/113703.451:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[0927/113703.451:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[7780:35508:0927/113703.468:ERROR:google_update_settings.cc(245)] Failed opening key Software\Chromium to set usagestats; result: 2
[0927/113703.468:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[0927/113703.468:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[0927/113703.482:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[0927/113703.482:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[0927/113703.482:ERROR:sandbox_policy_base.cc(358)] Failed to add sandbox rule. error = 2, subsystem = 0, semantics = 1, pattern = 'C:\DWASFiles\Sites\#1Rss1\VirtualDirectory0\site\utility\Puppeteer\Win64-686378\chrome-win\*.pdb'
[7780:33116:0927/113703.482:ERROR:browser_gpu_channel_host_factory.cc(138)] Failed to launch GPU process.
[0927/113703.576:ERROR:registration_protocol_win.cc(56)] CreateFile: Access is denied. (0x5)
[0927/113703.576:ERROR:file_io.cc(89)] ReadExactly: expected 36, observed 0
[0927/113703.576:ERROR:registration_protocol_win.cc(56)] CreateFile: Access is denied. (0x5)
[0927/113703.576:ERROR:file_io.cc(89)] ReadExactly: expected 36, observed 0

@emilbm
Copy link

emilbm commented May 12, 2020

@Jehoel

6. you'll see some stderr and/or stdout messages printed too. Unfortunately as Kudu doesn't forward Ctrl+C (or has any means of killing processes, really) you can't do anything and will need to open a new Kudu window to start again - but it shows that Chrome.exe can be made to start.

I've just managed to do the same before seeing your comment. I'm getting the same, but everything appears to be working. Have you experienced any issues with this approach of just ignoring the error? Memory-buildup or restarts or anything?

@GFoley83
Copy link

GFoley83 commented Sep 10, 2020

You can now use Puppeteer on Azure Functions running on Linux:
https://anthonychu.ca/post/azure-functions-headless-chromium-puppeteer-playwright/

Consumption plan only at time of writing. The article talks about Node.js but I've tested the code below and it works fine.

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    string url = req.Query["url"];
    url = url ?? "https://google.com";

    var downloadsFolder = Path.GetTempPath(); // Need to use a folder with write permissions. "/tmp/" in Azure 
    log.LogInformation($"downloadsFolder: {downloadsFolder}");

    var browserFetcher = new BrowserFetcher(new BrowserFetcherOptions
    {
        Path = downloadsFolder
    });

    await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);
    var browser = await Puppeteer.LaunchAsync(new LaunchOptions
    {
        Headless = true,
        ExecutablePath = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath
    });

    var page = await browser.NewPageAsync();
    await page.GoToAsync(url);
    var screenshotStream = await page.ScreenshotStreamAsync(new ScreenshotOptions { Type = ScreenshotType.Png, FullPage = true });

    return new FileStreamResult(screenshotStream, "image/png");
}

@sadidkhan
Copy link

@GFoley83 does the same implementation work on Azure Functions running on Windows also?

@daiplusplus
Copy link

@emilbm

Have you experienced any issues with this approach of just ignoring the error?

Honestly, no - I gave up :)

@nickticket2u
Copy link

You can now use Puppeteer on Azure Functions running on Linux: https://anthonychu.ca/post/azure-functions-headless-chromium-puppeteer-playwright/

Consumption plan only at time of writing. The article talks about Node.js but I've tested the code below and it works fine.

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    string url = req.Query["url"];
    url = url ?? "https://google.com";

    var downloadsFolder = Path.GetTempPath(); // Need to use a folder with write permissions. "/tmp/" in Azure 
    log.LogInformation($"downloadsFolder: {downloadsFolder}");

    var browserFetcher = new BrowserFetcher(new BrowserFetcherOptions
    {
        Path = downloadsFolder
    });

    await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);
    var browser = await Puppeteer.LaunchAsync(new LaunchOptions
    {
        Headless = true,
        ExecutablePath = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath
    });

    var page = await browser.NewPageAsync();
    await page.GoToAsync(url);
    var screenshotStream = await page.ScreenshotStreamAsync(new ScreenshotOptions { Type = ScreenshotType.Png, FullPage = true });

    return new FileStreamResult(screenshotStream, "image/png");
}

hey thanks for this solution. it works for english language. does anyone know a way to make the project to use unicode/east asian fonts for east asian websites ?

@GannonTank
Copy link

Any updated for deploy puppeteer in Azure Apps ? (OS version: Microsoft Windows NT 10.0.14393.0)
I execute the API and get the following error:
[ERR] An unhandled exception has occurred while executing the request. (48a46595) System.ComponentModel.Win32Exception (203): The system could not find the environment option that was entered. at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start() at PuppeteerSharp.States.ChromiumStartingState.StartCoreAsync(LauncherBase p) in C:\projects\puppeteer-sharp\lib\PuppeteerSharp\States\ChromiumStartingState.cs:line 68

@sashiyama
Copy link

sashiyama commented Mar 25, 2024

I've created a docker image to run a proxy server that provide WebSocket endpoint to use Chromium headless browser from your application. You can run it on your local environment or server such as render.com, Azure VMs, and so on even though your application is running on Azure App Service that does not allow apps to run headless browsers.

https://github.com/sashiyama/browserless

var options = new ConnectOptions
{
    BrowserWSEndpoint = "ws://localhost/chromium?token=xxx"
};

return await Puppeteer.ConnectAsync(options);

@BOBx5
Copy link

BOBx5 commented Aug 2, 2024

이제 Linux에서 실행되는 Azure Functions에서 Puppeteer를 사용할 수 있습니다: https://anthonychu.ca/post/azure-functions-headless-chromium-puppeteer-playwright/
이 글을 쓰는 시점의 소비 계획입니다. 이 글에서는 Node.js에 대해 이야기하지만 아래 코드를 테스트해보니 잘 작동합니다.

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    string url = req.Query["url"];
    url = url ?? "https://google.com";

    var downloadsFolder = Path.GetTempPath(); // Need to use a folder with write permissions. "/tmp/" in Azure 
    log.LogInformation($"downloadsFolder: {downloadsFolder}");

    var browserFetcher = new BrowserFetcher(new BrowserFetcherOptions
    {
        Path = downloadsFolder
    });

    await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);
    var browser = await Puppeteer.LaunchAsync(new LaunchOptions
    {
        Headless = true,
        ExecutablePath = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath
    });

    var page = await browser.NewPageAsync();
    await page.GoToAsync(url);
    var screenshotStream = await page.ScreenshotStreamAsync(new ScreenshotOptions { Type = ScreenshotType.Png, FullPage = true });

    return new FileStreamResult(screenshotStream, "image/png");
}

안녕하세요. 이 솔루션에 감사드립니다. 영어에서는 작동합니다. 동아시아 웹사이트에서 유니코드/동아시아 글꼴을 사용하도록 프로젝트를 만드는 방법을 아는 사람이 있나요?

@nickticket2u I had to add lines of codes on docker file.

RUN apt update -y && apt install -y fonts-noto-core && apt install -y fonts-noto-cjk && fc-cache -fv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Unplanned Not part of the actual roadmap
Projects
None yet
Development

No branches or pull requests