FCGI_ACCEPT(3)

πŸ’– FCGI_ACCEPT πŸ’–

okay bestie, we're looking at FCGI_Accept(3) β€” that's section 3 of the manual, the programming-functions zone. The whole lil squad on this page is FCGI_Accept, FCGI_ToFILE and FCGI_ToFcgiStream, and together they're the fcgi_stdio compatibility library. yes we are doing C today, hydrate first 🫢


✨ SYNOPSIS ✨

like, literally copy this into your file bestie:

#include "fcgi_stdio.h"

int
FCGI_Accept(void);

FILE *
FCGI_ToFILE(FCGI_FILE *);

FCGI_Stream *
FCGI_ToFcgiStream(FCGI_FILE *);

🌸 DESCRIPTION 🌸

So FCGI_Accept is the main character here. It accepts a new request from the HTTP server and then β€” the way that it does this is so iconic β€” it creates a CGI-compatible execution environment for the request. periodt.

the CGI plot twist πŸŽ€

If your app got invoked as a plain CGI program? Then the first call to FCGI_Accept is essentially a no-op (like, nothing happens, it's giving decorative) and the second call returns -1. And that's actually the point!! A correctly coded FastCGI Responder application runs a single request and exits, which gives you CGI behavior. slay.

the FastCGI server plot twist πŸ¦‹

But if your app was invoked as a FastCGI server, everything shifts:

  • the first call to FCGI_Accept is basically you saying "hey I finished my initialization, I'm ready for my first request πŸ’…"
  • subsequent calls mean "okay I finished processing the current request, hand me a new one"

And ooh, here's a fun one β€” an application can finish the current request without accepting a new one by calling FCGI_Finish(3). Then later, whenever it's ready for a new request, it calls FCGI_Accept. main character scheduling energy.

errors, ugh 😭

When it's completing the current request, FCGI_Accept may detect errors β€” for example a broken pipe to a client who has disconnected early (rude of them tbh). FCGI_Accept ignores such errors. If your app actually wants to handle those errors, you should explicitly call fclose(stderr), then fclose(stdout). An EOF return from either one indicates an error. no cap.

FCGI_WEB_SERVER_ADDRS πŸ”’

If the environment variable FCGI_WEB_SERVER_ADDRS is set when FCGI_Accept is called, it should contain a comma-separated list of IP addresses. Each IP address is written as four decimal numbers in the range [0..255] separated by decimal points. (nslookup(8) translates the more familiar symbolic IP hostname into this form, iykyk.)

So one legal binding for this variable is:

FCGI_WEB_SERVER_ADDRS=199.170.183.28,199.170.183.71

Then FCGI_Accept checks the peer IP address of each new connection for membership in the list. If the check fails β€” and yes, that includes the possibility that the connection didn't use TCP/IP transport β€” FCGI_Accept closes the connection and accepts another one, without returning in between. bye felicia, next caller please πŸ’…

after accepting ✨

After accepting a new request, FCGI_Accept assigns new values to the global variables stdin, stdout, stderr, and environ. After FCGI_Accept returns, these variables have the same interpretation as on entry to a CGI program. so cozy, so familiar.

THE MEMORY DRAMA πŸ’€ (read this part, fr fr)

FCGI_Accept frees any storage allocated by the previous call to FCGI_Accept. And this has important consequences:

  • DO NOT retain pointers to the environ array or any strings contained in it (e.g. to the result of calling getenv(3)), since these will be freed by the next call to FCGI_Finish or FCGI_Accept.
  • DO NOT use setenv(3) or putenv(3) to modify the environ array created by FCGI_Accept, since this will either leak storage or cause the next call to FCGI_Finish or FCGI_Accept to free storage that should not be freed.
bestie. I am begging you. do not hold onto those pointers. they WILL be yanked out from under you. πŸ™ˆ

If your application needs to use setenv or putenv to modify the environ array, it should follow this coding pattern:

char **savedEnviron, **requestEnviron;
int acceptStatus;

savedEnviron = environ;
acceptStatus = FCGI_Accept();
requestEnviron = environ;
environ = savedEnviron;
if(acceptStatus >= 0 && !FCGX_IsCGI()) {
    /*
     * requestEnviron points to name-value pairs in
     * storage allocated by FCGI_Accept.  OK to read,
     * not OK to retain pointers -- make copies instead.
     */
}
/*
 * OK to do setenv or putenv, but beware of storage leaks!
 */

env vars, the extended universe 🌈

In addition to the standard CGI environment variables, the environment variable FCGI_ROLE is always set to the role of the current request. The roles currently defined are:

  • RESPONDER
  • AUTHORIZER
  • FILTER

In the FILTER role, the additional variables FCGI_DATA_LENGTH and FCGI_DATA_LAST_MOD are also defined. See the manpage FCGI_StartFilterData(3) for complete information. πŸ‘‘

the escape hatches 🧚

The macros FCGI_ToFILE and FCGI_ToFcgiStream are provided to allow escape to native functions that use the types FILE or FCGI_Stream. In the case of FILE, functions would have to be separately compiled, since fcgi_stdio.h replaces the standard FILE with FCGI_FILE. yes, it's a whole thing.


⭐ RETURN VALUES ⭐

  • 0 β€” successful call, we ate πŸ’…
  • -1 β€” error, and the application should exit

πŸ‘‘ SEE ALSO πŸ‘‘


πŸ’œ HISTORY πŸ’œ

Copyright (c) 1996 Open Market, Inc. See the file "LICENSE" for information on usage and redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.

okay that's the whole page bestie, go forth and accept those requests responsibly 🫢✨


and that's a wrap on the FCGI_Accept(3) page, which came to you straight from $Id: FCGI_Accept.3,v 1.1.1.1 1997/09/16 15:36:25 stanleyg Exp $ β€” yes, 1997, she's vintage, she's a classic, and she's still slaying πŸ’– bye!! πŸŽ€πŸ¦‹