kristapsdz / kcgi

minimal CGI and FastCGI library for C/C++
https://kristaps.bsd.lv/kcgi
ISC License
278 stars 40 forks source link

[Help wanted] FastCGI with kfcgi on macOS #40

Closed nalzok closed 6 years ago

nalzok commented 6 years ago

I need some help using FastCGI with kfcgi on macOS. By now I've built the executable, but I have no idea how to configure the server.

Actually I don't even know which server I'm using! macOS ships with a built-in server, but I'm not sure whether it's Apache or httpd, since both names seem to refer to the same thing.

~|⇒ apachectl -v
Server version: Apache/2.4.33 (Unix)
Server built:   Apr  3 2018 18:00:56
~|⇒ httpd -v
Server version: Apache/2.4.33 (Unix)
Server built:   Apr  3 2018 18:00:56

Anyway, I followed your tutorial on working with httpd, but the server complains about a syntax error when I added the server "me.local" command into the configuration file /etc/apache2/httpd.conf.

~|⇒ apachectl -t
AH00526: Syntax error on line 564 of /private/etc/apache2/httpd.conf:
Invalid command 'server', perhaps misspelled or defined by a module not included in the server configuration

I tried consulting the document but was soon overwhelmed by the huge amount of info: which module should I use, mod_fastcgi, mod_fcgid, or mod_proxy_fcgi? It would be great if you could provide an example, since most people don't have a machine running OpenBSD by their hand (remote servers are an option, but the connections are usually quite slow!)

kristapsdz commented 6 years ago

The tutorial mentioned is for OpenBSD's httpd. I don't have any information on Mac OS X's Apache. You might want to start by searching for running CGI scripts on Mac OS X, then FastCGI---which will be much more complicated. kcgi's FastCGI scripts should work with kfcgi or the default Apache runner.

nalzok commented 6 years ago

I've managed to use this library with CGI on macOS, which is quite straightforward with your detailed tutorial, but working with FastCGI is indeed much harder!

I'll update this thread if I can get it to work.

nalzok commented 6 years ago

I don't know it's a good news or a bad one. Either way, I believe I've configured NGINX on macOS to work with the FastCGI protocol, but the result is a kernel panic. (Edit: you can fix this by passing -v to kfcgi, the reason behind this is very likely a macOS bug)

First, you need to build and install the application:

cc -I/usr/local/include -c -o fastcgi-app.o main.c
cc -L/usr/local/lib -o fastcgi-app fastcgi-app.o -lkcgi -lz
sudo mkdir -p /var/www
sudo install -m 0555 fastcgi-app /var/www

Note that I dropped -static, because it's not supported on macOS. As a workaround, we're going to copy all the dynamic libraries over to get the executable to work inside the file-system jail:

sudo mkdir -p /var/www/bin /var/www/usr/lib/system
sudo cp /bin/* /var/www/bin
sudo cp -R /usr/lib/* /var/www/usr/lib
sudo cp -R /usr/lib/system/* /var/www/usr/lib/system

Next, install NGINX with brew install nginx and edit /usr/local/etc/nginx/nginx.conf to add the following server configuration:

server {
    listen       8080;
    server_name  localhost;

    location / {
        fastcgi_pass unix:/var/www/run/httpd.sock;
    }
}

Now you can start NGINX by simply typing nginx into the terminal. The last step is to start the kfcgi FastCGI server:

sudo kfcgi -U `whoami` -u `whoami` -- /var/www/fastcgi-app

Nonetheless, as mentioned before, I got a kernel panic when visiting localhost:8080, which I presume as the result of my correct configuration. Correct me if I'm wrong, but now I think the bug mentioned in #39 wasn't triggered by the regress suite.

In this case, the application I used is the minimal example provided by your tutorial:

#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <kcgi.h>

int
main(void)
{
  struct kreq req;
  struct kfcgi *fcgi;

  if (KCGI_OK != khttp_fcgi_init
     (&fcgi, NULL, 0, NULL, 0, 0))
    return 0;

  while (KCGI_OK == khttp_fcgi_parse(fcgi, &req)) {
    khttp_head(&req, kresps[KRESP_STATUS], 
      "%s", khttps[KHTTP_200]);
    khttp_head(&req, kresps[KRESP_CONTENT_TYPE], 
      "%s", kmimetypes[KMIME_TEXT_PLAIN]);
    khttp_body(&req);
    khttp_puts(&req, "Hello, world!\n");
    khttp_free(&req);
  }

  khttp_fcgi_free(fcgi);
  return 0;
}

When I run /var/www/fastcgi-app directly on the command line, it just hang up without causing a kernel failure, so I suspect that the offending line lies in khttp_fcgi_parse.

kristapsdz commented 6 years ago

Great job! I don't think it's worth digging around on this more: obviously there are some show-stopping bugs in Mac OS X. Thank you so much for spending the time to uncover these! I'll definitely take Apple off the list of supported systems.

nalzok commented 6 years ago

No problem, and you've also done a great job!

While it's regrettable to hear that you're going to drop support for macOS, I would say you've made a sensible decision, for it really doesn't qualify for a web server, at least not in the near future.

kristapsdz commented 6 years ago

I'll leave support enabled in case it's fixed, but just put up a PSA on the kcgi site that it might crash and shouldn't be trusted. You can always try basic CGI scripts---but first see if something like the abort test case, where a validator abort()s, crashes the system as it did in the regression suite; and if it does, just... make sure your systems never abort. :( Either way, you get full credit for this discovery. Thank you so much for your research!

As for FastCGI, variable mode (-r) might make a difference, but I doubt it. My uninformed guess is that Mac pukes because of something regarding socketpair IPC.

nalzok commented 6 years ago

You're welcome :)

Yeah I have no problems playing with CGI, not counting the test-abort-validator case. When it comes to FastCGI, I just tried variable mode, and it works on my system!!! You may want to include this piece of information into the PSA.

~|⇒ sudo kfcgi -r -p / -U `whoami` -u `whoami` -- /var/www/fastcgi-minimal
Password:
~|⇒ nginx
~|⇒ curl -i localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.15.0
Date: Thu, 14 Jun 2018 16:55:18 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

Hello, world!

PS: just a quick question, what does the -- do in the call to kfcgi? Everything seems to work well after I drop it, i.e.

~|⇒ sudo kfcgi -r -p / -U `whoami` -u `whoami` /var/www/fastcgi-minimal

(I'm reopening this issue because it appears that you won't receive a notification when I comment under a closed issue.)

kristapsdz commented 6 years ago

The -- indicates an end to optional arguments. See getopt(1) for details. Thank you again!