Over the course of about the last month, I've been working out the solution to a product limitation that's been bothering me for a long time. It deals with generating real-time personalized content for the web. I guess I should be slightly vague in regards to the specifics, but I can talk about some interesting tidbits...
Up until this point, our team has been using Flash to deliver this content on the client-side. It makes sense for the use case in general, but it has some obvious compatibility issues. So, for a long time - a year or so, I've been intermittently researching how to generate this content on the server side, then deliver everything up fully rendered and ready to view. And during the long Thanksgiving weekend, I came across phantomjs.
What phantomjs enabled me to do was to use a headless browser as a render engine. I had looked at doing this with some kind of server-side AIR application, but I'm not sure such a thing is possible. Setting up the page and graphics to render was the easy part, but what this choice lead me down was a nearly obsessive delve into server functionality and especially permissions. I wanted to be able to log onto my machine from another device and run this process - delivering non-Flash, personalized content to the browser.
For the most part, I use MAMP for my localhost management. MAMP makes it extremely easy to start an Apache server running php (and mysql) in whatever directory you choose. So getting the development environment set up was also a piece of cake. But the first and biggest hurdle came when trying to kick off the phantomjs process using php. I could not get it to start. I had a php system call going, but it wouldn't fire. I could run other server processes, but nothing with phantom. I eventually found that there were some errors logs being generated in the Mac console app. Stuff like this...
Process: phantomjs [44842]
Path: /Users/USER/Desktop/*/phantomjs
Parent Process: sh [44840]
The logs didn't really help, though - told me nothing. It became clear to me as I started poking around that I was dealing with permission problems. Running $ ls -l phantomjs from terminal gave me these permissions for phantom: -rwxr-xr-x@. The @ threw me because I hadn't noticed that on anything before. That seems to be a Mac OS X addition for downloaded items and can be removed. Still didn't help, though. Next try was to modify the sudo user permissions for phantomjs only. Admittedly, it's probably best not to open that up, but it was worth trying. Still nothing.
I eventually moved on from the server stuff to get to the point where I could run the process I wanted to complete from the command line at least. This put some fun back in the project and I was able to get the kind of results I wanted to see. Once everything was in place, I decided to try the built in Mac server as opposed to MAMP. It's easy enough to start web sharing from your system preferences, but php is not enabled by default. This was a very helpful guide to get that started - especially the PHP section; uncommenting the LoadModule line.
So the files were in place, the server was running, and I still couldn't get phantomjs to fire from my page. Delving into permissions once more I found this useful guide. That's when I realized the Apache user did not have executable privileges for phantom (which doesn't seem to map directly to the problems I was having with the MAMP server). Running $ sudo chmod o=rx phantomjs allowed me to open up the binary to be run by other users. Finally everything came together. There is another server tool used in the process I designed, so instead of just running phantom, I decided to pull my server actions together into a simple shell script. I did a simliar chmod to that script in order to fire it from php.
I now have a fully functional proof of concept running from my machine, and I've been showing it around. It needs a whole lot of optimization before we can deploy anything, though, and I'm still not totally sure how secure it is to start modding permissions on some of that stuff; it's all very brute force. But for my local testing, and in order to finally pull off something I've been researching a long time, it works great!