fcgi
Some ancient but very performant technique. Here is a quick guide to get it working with apache2 and libfcgi.
introduction
The principle is to have a server running at a given port, possibly even with a unix socket connection. The server is started up separately using the spawn-fcgi program. Apache2 is configured to talk to the server.
documentation
installation
Mostly we need apache2 running, and libfcgi and spawn-fcgi for the server.
| install | |
|---|---|
the apache config than has to be setup to redirect certain requests directly to the fcgi program loop. A rather minimal config would be :
| apache | |
|---|---|
Note that the servername seems to be needed. And when you can't use localhost anymore. But now it is reachable from all machines in the network.
Do NOT use enablereuse=on because this does result in crashing behavior.
Really use localhost NOT 192.168.1.151, or setup the proxy to use that ip address.
For the planner app, this means changing the line in src/environments/environment.ts to :
This just can be an extra line added to an existing site, very easy. Note that it is an extension of mod-proxy that we are using !!, apache relays the requests to port 8000 as a normal proxy.
Note also that a multi-server solution would be something like :
| multiple fcgi services | |
|---|---|
The example at apache use localhost with two different ports, so this may have to be tested first.
Now everything for /ws get's sent to localhost port 8000. At this moment nothing is listening there so :
| wget tryout | |
|---|---|
the server
We need a program that listens for FCGI requests in a loop and handle them. Here is a simple echo implementation. :
When you compile this and run it nothing much happens:
But spawn it with this command:
Now you can browse to visit
You will see a page dumping the whole environment, if you look at REQUEST_URI you will see
| uri | |
|---|---|
So it can be used to build a REST interface quit easy. Keep this echo implementation around for debugging purposes.
stopping the server
Practical guide :
| stopping | |
|---|---|
building the server
Now to get more out of this, more will follow. First lets tryout a multi-thread version because we do want the server to remain reactive. Most request will take more than seconds so we don't want to wait for the results but must be able to accept the next request.
The main outline is :
debugging fast CGI
The standalone method is more powerful since you can also test valgrind etc. but the gdb attach method is still very useful too.
standalone method
This discussion tries to open the socket as a unix socket :
If this link dies: this is the solution :
| debugging | |
|---|---|
This does startup the server locally, but how to reach the socket ? Then this discussion mentions it can be on a port as well :
In short, open the socket like this :
| open socket | |
|---|---|
See fcgi.c in the backend server for a working version of this. Now you can valgrind the server !!
| profile | |
|---|---|
gdb attach
The best way I see is attaching gdb to the process id of the fcgi server and setting a breakpoint.
| gdb | |
|---|---|
Now you start in a halted gdb session so you can move up and down the stack to decide where to put a breakpoint. I would suggest just after the FCGX_Accept_r() call. Then continue the server and post a request on the apache site.
Also as a debug aid you can print anything onto the webpage but a header is needed because it is to the browser, so :
Of course you don't need to use the browser, the old test scripts worked on the url endpoint '/ws/' so after changing the loop into a fcgi loop and configuring apache to proxy '/ws/' to the 'new' klopt_rte server. The out put of the above program delivers this :
| test ping | |
|---|---|
Now we like to detect if this is a POST or GET, but which parameter to get. A handy function to dump the complete environment was printed earlier : PrintEnv(), and it is very helpful to have that present for debugging. Also i keep forgetting to print the header, and you get no output without it so :
In the list printed you can clearly see : REQUEST_METHOD=POST and CONTENT_LENGTH=41. (this was for a ping example) Strangely just reading from either stdin or FCGX_stdin does not give anything, and so does reading with FCGX_fread().
The only way to get this working is the example from libfcgi itself, the echo-cpp.cpp program : https://github.com/jocelyn-old/libfcgi/blob/master/examples/echo-cpp.cpp
The main part we used is this function :
| echo-cpp.cpp | |
|---|---|
It uses a separate function for reading the POST data, and also it replaces the cin,cout and cerr handles for the duration of the loop and replaces them with the ones from the 'request'. That does not seem actually necessary so try to make a shorter version (todo)
cors problems
First of all uninstall the CORS plugin that was advised by the angular tutorials to get rid of this error :
Error
'Access-Control-Allow-Origin' header contains multiple values 'http://evil.com/, *', but only one is allowed. Origin 'http://my-app-name.rhcloud.com' is therefore not allowed access.
The extension writer thought to be clever in adding http://evil.com as a reminder that CORS is useful. However this leads to another error because it now specifies two options. Disable the extension and do it in apache2 ! : In the VirtualHost section where the ProxyPass line is add These Header lines :
| allow-headers | |
|---|---|
We only get the CORS message because or web service is on a different port but still localhost. Reload apache and if you get an error don't forget to :
2023 findings
I first got much trouble starting the backend program but it probably is because the command line is not a feasible way to start the server.
If you compile it standalone it will start, but it never listens to connections.
telnet connect will detect that something is listening on port 8000, but it won't enter the code after accept.
WEB_VERSION
In the makefile you can set this value to create a version that is started by apache itself.
Disabling WEB_VERSION does not make debug/backend standalone !!
It still only work through fcgi + apache !! You just start it from the command line.
The non web version is very handy for debugging, because you CAN start it under gdb !
Just don't try to connect to it's port (6666)!!
It will not work !. If you would want that, you have to use a plain listen/accept.
You can get the data by browsing to http://192.168.1.151/ws/rest/orders. Or with wget.