How to use Bryntum PDF Export server with Microsoft IIS server

November 01, 2023

This small how to is targeted at people who want to run the Bryntum https://github.com/bryntum/pdf-export-server with IIS server if they host it’s JS part in for example ASP.NET application.

So lets break down possible problems I was able to troubleshoot.

How to run the server

First problem you might encounter is that the PDF export server will run under NodeJS 16 for now. I asked (here https://github.com/bryntum/pdf-export-server/issues/16) if they will try to update to the latest LTS but… not response yet. You can try to update on your own since the code is public but that is extra work.

Quick fix (to force NodeJS v16 on your prod machine) is to download portable NodeJS from https://nodejs.org/dist/ and take one for your machine with .zip extension which is version you will not need to install (I like to call them portable since there is this page I like https://portableapps.com/)

With this version placed somewhere on your machine can can do this :

nodejs.exe "path/to/PdfExportServer/src/server.js"

which will start the server for you on http://localhost:8080. For further information on cmd line arguments refer to the documentation here: https://github.com/bryntum/pdf-export-server/blob/main/docs/configuration.md

Authentication

It is a good idea to create a reverse proxy to not directly connect to the PDF export server but rather have a URL where you can access it like a part of your application. Then the requests also need to be authenticated. Since there is auth built in the PDF export server, it will not by default send cookies to IIS thus the request to working URL (from browser which automatically sends cookies) so you might have 401 error.

Documentation to the rescue : https://bryntum.com/products/gantt/docs/api/Grid/feature/export/PdfExport#config-fetchOptions which boils down to sending this prop

fetchOptions: { credentials: "same-origin" }

There is JSON payload sent back and rendered PDF fails to download

The HTTP POST that sends data to render as PDF gets just JSON response with link to the PDF export server to download the rendered response. It unfortunately seems that this will always be rendered with name of server https://github.com/bryntum/pdf-export-server/blob/main/src/server/WebServer.js#L109 and I was not able to get around this differently than to use another prop and get PDF as response with help of this property : https://bryntum.com/products/gantt/docs/api/Grid/feature/export/PdfExport#config-sendAsBinary which again translate to this

sendAsBinary: true

You might need to tweak the maximum accepted payload and number of workers

This really depends on how you will be using Bryntum Scheduler or any other lib that renders PDF but it seems on our end we had to tweak the default of 50MB incoming payload and default number of workers which ended up on our side to be 10 for both not killing the machine where PDF export server is running and also making the PDF faster from defaults. Both are cmd line properties like this

--maximum=100mb --max-workers=10

How to start the PDF export server as Windows service

To not start the PDF export server by hand you might want to automate things a bit. You can take the Docker image from https://hub.docker.com/r/bryntum/pdf-export-server or alternatively use this package https://github.com/coreybutler/node-windows and create service. These are the samples to install and uninstall the service with node-windows.

install script (execPath is just sample here)

var Service = require('node-windows').Service;

// Create a new service object
var svc = new Service({
  name:'Bryntum PDF Export Server',
  description: 'Starts NodeJS PDF export server for Bryntum charts',
  script: 'src\\server.js',
  scriptOptions: '--maximum=100mb --max-workers=10',
  execPath: 'c:\\Program Files\\iisnode\\node-v16\\node.exe',
  nodeOptions: [
    '--harmony',
    '--max_old_space_size=4096'
  ]
  //, workingDirectory: '...'
  //, allowServiceLogon: true
});

// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
  svc.start();
});

svc.install();

uninstall script

var Service = require('node-windows').Service;

// Create a new service object
var svc = new Service({
  name:'Bryntum PDF Export Server',
  script: 'src\\server.js',
});

// Listen for the "uninstall" event so we know when it's done.
svc.on('uninstall',function(){
  console.log('Uninstall complete.');
  console.log('The service exists: ',svc.exists);
});

// Uninstall the service.
svc.uninstall();

How to reverse proxy under IIS

This one was simple , you need to install https://www.iis.net/downloads/microsoft/application-request-routing. Stupid thing is that you might end up with some errors. First of all settings where to redirect are done in web.config file and since at the bottom of the page above there is small tiny note

ARR depends on URL Rewrite. Ensure URL Rewrite is installed prior to installing ARR.

you might by accident end up in situation where some devs already have https://www.iis.net/downloads/microsoft/url-rewrite installed and changes in web.config will not do anything but without ARR things will not work as expected. But some ppl might end up with yellow screen of death without knowing why. So please beware of this.

Also you might end up seeing something like 502.3 error which turned out to be ARR switched off

IIS ARR switched off by error

I recommend looking here https://github.com/MicrosoftDocs/iis-docs/blob/main/iis/extensions/configuring-application-request-routing-arr/creating-a-forward-proxy-using-application-request-routing.md#user-content-configure-arr-as-a-forward-proxy where MS ppl made quite nice “how to”.

Hope you saved some time.


Profile picture

Written by Dušan Roštár - the "mr edge case" guy
my twitter : rostacik, my linkedin : rostar, drop me an email : here