Which crate for FCGI/fastCGI server is recommended?

  • “fcgi” was yanked. Any idea why? (Github Copilot recommended it.)
  • “fastcgi” doesn’t parse or create headers.
  • “fastcgi-server” seems to be an empty project.
  • “vintage” - might work.
  • “gfcgi” - might work

Any recommendations?

(Why FCGI? Runs on low-cost Apache-based shared hosting with good performance. I’m using Go for this now, and it’s been running for years with zero attention.)

fcgi was probably yanked because it’s been abandoned for 10 years.
gfcgi has been abandoned for 8 years, so don’t use it.
vintage is probably your best bet.

I strongly recommend looking into a cheap VPS if you can; the performance and security benefits are well worth it.

Thanks. What I want is a Rust equivalent to Go’s fcgi package - net/http/fcgi - Go Packages

That’s what FCGI calls a “responder”. It doesn’t do any network I/O. A web server module, such as mod_fcgid in Apache, calls responders (executable .fcgi files) which read requests from stdin and reply via stdout. It’s like CGI, except that FCGI programs contain a loop to get, process, and reply to requests. So the responder program is not loaded for each request. mod-fcgi will start up and shut down responder programs as needed, depending on load. There’s a whole orchestration system in there, decades before Kubernetes. This lets you get a lot done on minimal servers.

Looking at the Rust options, what shows up is mostly programs that listen on a socket and fire off responders. Don’t need that part; Apache does that. I just need the pure responder part, which is very simple.

  • vintage has a different architecture. It wants “responders” written as always-running programs, and communicates to them via a local socket.
  • outer-cgi has roughly the right functionality, but the example in the docs uses a trait as a type and it won’t compile. (Rust change: dyn now mandatory.) Fixed that, now getting an error message from the FCGI server.
  • async-fcgi fcgi-client akiaki-fcgi fastcgi-client flash_rust_ws all do their own network I/O. Not allowed on shared hosting.
  • bbox-server, bbox-map-server fastcgi-healthcheck - special purpose
  • gfcgi v0.4.3

In Go, it Just Worked. Anyone actually do this any more?

Probably not. The world has largely moved away from shared hosting to VPS and from Apache to reverse proxies like nginx, caddy and traefik.

I guess this perhaps happened when going to docker containers: those work great with reverse proxies, but not with fcgi.

Apache is still at 27% market share, bigger than anything except ngnix.

I don’t want to move this server to something different, more expensive, and more complicated. It’s mostly running Go programs via FCGI. They’ve been running for seven years with zero attention, logging events to a MySQL database. Hard to beat that.

outer_cgi turns out to have terrible unsafe code. They wrote C in Rust:

unsafe {
std::ptr::copy((&self.recvbuf).as_ptr()
.offset(self.recvbufpos as isize),
(&mut self.recvbuf).as_mut_ptr(),
self.bytes_left_in_recvbuf() as usize);
}

And, sure enough, there’s a security advisory for a buffer overflow.

Their example doesn’t work right under Apache. It’s apparently not writing out the correct headers, and the server checks that.

Is there anything amongst all the Rust implementations of FCGI stuff that works properly in Apache FCGI mode?

2 Likes

Worst case, you write the support library yourself and then publish it if you're proud of what you've done. Libraries are usually not general enough until they've gotten 3 serious users.

4 Likes

Well, it’d be entirely possible to wire up pipe file descriptors as the initial stdin/out of a container’s pid1. I suspect it’s just that nginx&co never saw a reason to start playing that game when http1.1 connection reuse works well enough for proxying these days and most languages have http servers that can be run behind the proxy.

One case I can think of where CGI still makes sense is resource-constrained systems like consumer routers where you might want to script a few endpoints into their built-in webserver.

1 Like

I wrote a simple HTTP server with CGI scripts and websocket support. Check it out. So far, I run currently a bunch of Rust app on it. But sure, it didn’t reach super big production quality yet.

That’s the other side of the interface - the thing that calls CGI programs. I need the library for the called part.

I want the part that gets executed. If you name something “foo.fcgi” and put it in a directory Apache looks at for .fcgi programs, it will be run under mod_fcgid when an external connection references the relevant URL. This is really convenient for Rust and Go programs, which are self-contained.

There’s a protocol by which the two talk. It’s very C-oriented, with lengths and offsets. A pain to parse, and difficult to debug. Go has the functions for this, and I’m trying to find them in all the various Rust FCGI implementations.

The Go implementation has the advantage that fcgi is net/http/fcgi, an integral part of the one approved http package. So it can parse FCGI headers into the same header format that http uses. In Go, this Just Works. Rust has lots of HTTP header parsers, with various bugs.

It took me about twelve lines of Go for the basic part of a FCGI responder. Still trying to do it in Rust.

At this point it does look like you will need to make your own (or fork an existing library). I took a quick look at the protocol, and the most annoying part seems to be structs with multiple trailing DST fields (rust only supports a single trailing DST field).

Should you choose to make your own, there are a few options:

  • winnow is a parser combinator library that can parse binary formats as well as text based formats.
  • If you want to go for the best possible performance with minimal copying of data, you might want to look at the zerocopy crate for some support functions.

Those are the two things that come to mind immediately, but there are other parser libraries that could help too, it might be a good idea to look around and see which one you like.

Just because something is abandoned doesn't strictly mean you shouldn't use it. It isn't necessarily more vulnerable than something you'd write yourself.

fcgi itself hasn't changed, so it won't be less compatible.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.