Running Native Code on OLS (i.e. CGI, FastCGI, SAPI, etc)

29 views
Skip to first unread message

Mike Kasprzak

unread,
May 31, 2016, 10:22:46 PM5/31/16
to OpenLiteSpeed Development
Hello,

So I've been digging in to how you make OpenLiteSpeed run external programs, as well as schooling myself on the history of these things (CGI, FastCGI, etc).

I realize that CGI has limitations, and potential bottlenecks with startup performance. Best I can tell, OLS can only execute CGI programs directly, and can't be configured as an "External App" that parses other scripts. This might have been nice to have for getting basic processing working (i.e. rigging up a shell script that calls ImageMagick to perform automatic conversion to WEBP, or FFMPEG to extract a video thumbnail).

At the moment I have a very basic FastCGI program sort-of working... well, not actually working, but I'll get to that. I'm pretty sure I get how this is supposed to work. You set up the External App, then either a Script Handler or Context to forwards the requests to the External App. I'm using a context for this, a specific URL (/test/), and when I visit that URL it appears to work... and by that, I mean it times out (503's) after a few seconds, just as it's configured. :). I wasn't able to find my program running in the background, so I suspect it's somehow related to that.

Anyway, I've only *just* started debugging this. I'm not too concerned about finding a solution right now, but if you have advice for debugging FastCGI programs with OLS I'd be happy to hear it (my log is pretty bare, just a message telling me it "stop worker process").

To the point: Is there documentation, or "hello world" sample code for creating a SAPI plugin?

I am a bit nutty when it comes to performance (I spent many years writing video games for low spec/embedded systems). I realize CGI programs have an application startup cost, and that both CGI and FastCGI have to communicate via Sockets, but I'm the sort of fanatical dev that likes the idea of eliminating bottlenecks when I see them. Elsewhere I use a PHP library APCu, which is much the same idea (socketless memory caching), to much success.

My needs are simple. Like CGI and FastCGI, I need to be given input (a URL, GET and POST arguments, the other env variables), and I want to spit out some output. Let OLS handle the networking and transport for me, even let it gzip my data if it so desires. I just want to be told what to do. :)

Or perhaps what I'm proposing isn't the best way to do what I want with OLS. Feel free to suggest alternatives.


What I am doing: At the moment it's just a proof-of-concept, but what I'm trying to get working is wrapping the CSS parser "Sass" (specifically the C library libsass), in such a way that my server automatically runs all CSS files through it before sending them to the client. I realize Sass was originally a Ruby library, but I'm interested in the potential of hooking up native code to URLs in OLS. I can then add some basic smarts to it (makefile style, if the modified time changes then recompile the file, otherwise send a cached copy), but once I do that, my new bottleneck becomes how I receive and send the data to OLS.

Anyway, thanks for all you do with OLS. As I play with it more, it becomes more and more one of my favourite pieces of software. :D

Regards,

Mike Kasprzak

Kevin Fwu

unread,
Jun 1, 2016, 3:46:17 PM6/1/16
to OpenLiteSpeed Development
Hi Mike,

I hope that I understood you correctly. Please correct me if my replies are incorrect.

Problem 1: No real log. I'm assuming you mean you need to print some debug messages from php?
I don't know if you tried getting xdebug to work, but that + an IDE like NetBeans is useful for debugging with breakpoints.
If you want to/are fine with just printing stuff, using error_log() will print to the server's error log (default is lsws/logs/error.log).
You can do something like:
error_log('Hello World!'); // prints Hello World! to error log.
error_log('My class innards ' . print_r($myClass, true)); // prints members of my class to the error log.

In php, global variables like $_SERVER, $_REQUEST, $_GET, $_POST, $_COOKIE are available. These are all arrays, so you can use the print_r technique mentioned earlier to print out the input.

Problem 2/main point: You are trying to implement something that utilizes libsass for all of your requests to do some parsing.

We have a beta module system available in OLS. It currently works, but is untested. It is also not finalized, so some things may change (nothing crazy, unless it's a major change to the server).
The module system provides a place for users to hook into the server processing, and if I understand you correctly, that's exactly what you're looking for.
In the downloaded directory (the directory you get after untarring the package), there should be a subdirectory addon. In addon/example, there should be a ccc.sh and a list of .c files. 
ccc.sh is the compiling script. This is used to create the .so file to add to your module list.
The .c files are sample modules that you can look through to get an idea of what to do (we don't have a guide out yet).

Also in the downloaded directory, there is a subdirectory include. In here, you will find ls.h, lsdef.h, and a lsr subdirectory.
ls.h is the file with most of the constants and functions for you to use to hook into the request processing stages.
lsdef.h has some more defines, small file, but if you were interested, this is here.
lsr/ contains the litespeed runtime class prototypes. These are here for you in case you want to use some specialty classes.

After creating your module and compiling it with ccc.sh, copy the .so to your installation directory, into lsws/modules/.
Once copied, you will need to add the module via the web admin. It must be added at the server level. You may individualize the enable/disable at the vhost/context levels, but it must be added at the server level at a minimum.

Hope this helps, if I didn't answer your questions let me know!

Cheers,
Kevin
Reply all
Reply to author
Forward
0 new messages