Rendering images in a webshot pdf on Meteor's Galaxy

I posted this just a little while ago over on SO. I was wondering if anyone else has had issues rendering pdfs with webshot on Galaxy’s servers. @ryanswapp, you wrote a pdf tutorial a while back. Is it hosted with Galaxy, or another server? :

"I have a pdf that is rendered from a server side html file in my
Meteor application using webshot. This pdf is displayed in the browser,
and also attached to an email to be sent to various users. Since
migrating over to Meteor’s Galaxy platform, I am unable to render the
images in the html file, and the email attachment doesn’t work
correctly. My set up worked perfectly on Digital Ocean with Ubuntu
14.04, and also on my localhost. It still works perfectly at both of
these environments, but doesn’t work with Galaxy. (it’s worth noting I
don’t know much about programming email attachments, but used Meteor’s
email package, which is based on mailcomposer)

The pdf renders, so I know phantomjs is working, and webshot is
taking a screenshot and displaying it as a pdf, so I know webshot is
working. However, the images won’t render and when attaching to an
email, the file is corrupted/doesn’t send correctly. I have tried
logging the html to ensure that the URLs to the image files are all
correct, and they are when deployed to Galaxy, but they just won’t
render with phantomjs/webshot. I am using the meteorhacks:ssr package to
render the html file on the server before reading it with phantomjs.

I’ve tried contacting Galaxy support about this, but haven’t had much
assistance. Has anyone else experienced this? I’m struggling to even
pinpoint the package causing the issue to submit a pull request if I
need to. Thanks!"

1 Like

@bsbechtel Hey so I have also had some trouble deploying to galaxy (site is now on DO) due to npm binary issues. I’m not sure if its related to what your experiencing though. Are you sure the PDF is rendering? Also, what version of Meteor are you using? Webshot works fine locally with Meteor 1.3 but then fails in production if you are using Modulus/Galaxy/Mup. None of these tools rebuild npm modules for the specific environment so any modules with binaries will throw errors. Mupx works as it builds the whole environment in docker.

@ryanswapp, I’m still at Meteor version 1.2.1. The pdf is definitely rendering. I can pull the pdf route up in a separate window, and it renders fine (minus the image that isn’t loading). I think it is an issue with how phantomjs is configured, or the phantomjs version, because webshot has some open github issues with certain phantomjs installations. However, the Galaxy team hasn’t provided much info on the phantomjs installation in their Galaxy containers to be able to diagnose anything from there.

So I figured out my problem, which I’ll share with others, but I’ll also share a few pointers on debugging webshot in an app running on Galaxy’s servers.

First, webshot doesn’t pipe errors to the Galaxy’s logs by default, as it’s running on a spawned node.js process, so you need to change this line in your ‘project_path/.meteor/local/isopacks/npm-container/npm/node_modules/webshot/lib/webshot.js’ file (note, I’m still on Meteor 1.2, so this is wherever your npm webshot package is located):

// webshot.js line 201 - add , {stdio: “inherit”} to spawn method
var phantomProc = crossSpawn.spawn(options.phantomPath, phantomArgs, {stdio: "inherit"});

This passes all logs from the spawned process to your console. In addition to this, comment out the following code in the same file:

// comment out lines 234-239
// phantomProc.stderr.on(‘data’, function(data) {
// if (options.errorIfJSException) {
// calledCallback = true;
// clearTimeout(timeoutID);
// cb(new Error(’’ + data))
// }
// });

Doing these two modifications will print logs from the phantomjs process to your Galaxy container. In addition to that, you will want to modify the webshot.phantom.js script that is located in the same directory to print to the console in order to debug. This is the script you will want to modify however you see fit to find your issue, but the phantomjs docs recommend using phantom callbacks to debug errors from the web page being loaded, such as:

page.onResourceError = function(resourceError) {
  console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
  console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

For my particular issue, I was getting an SSL handshake issue:

Error code: 6. Description: SSL handshake failed

To fix this, I had to add the following code to my webshot options object:

        phantomConfig: {
          "ignore-ssl-errors": "true",
          "ssl-protocol": "any"
        },

This fixed the issue with loading the static images in my pdf over https (note: this worked correctly on Digital Ocean without the code above, I’m not sure what is different in the SSL configuration on Galaxy’s containers).

In addition, I was having issues with attaching the pdf correctly to an email my app sent. This turned out to be an issue with rendering the url correctly for email using Meteor.absoluteUrl() in the mailcomposer attachments filePath object. I don’t know why Meteor.absoluteUrl() did not render my app’s url correctly on Galaxy in an email attachment, as Meteor.absoluteUrl() works in other places in my app, and it worked on Digital Ocean, but it didn’t work here. When I switched the attachment object over to a hard coded URL, it worked fine, so that might be something worth checking if you are having issues.

I know quite a few Meteor developers have used webshot to create pdf’s in their app, and I’m sure some will be migrating to Galaxy in the future, so hopefully this is helpful to others who decide to switch to Galaxy. Good luck!

1 Like

What worked for me were the following command line options (example):

PhantomJsJob = ChildProcess.exec "phantomjs --ignore-ssl-errors=true --ssl-protocol=any --web-security=false " + AbsoluteScriptPath

Reference: http://phantomjs.org/api/command-line.html