ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm a C++ developer who has never touched any web development stuff before Save from making basic html/css pages.
I have a one-board-computer-based device (Raspberry-Pi) where I want a customizable webpage, and provide the possibility to have a custom FastCGI program be run that takes care of dynamic stuff.
The webserver used is nginx, which I configured to point to the directory for html / index page, and forward FCGI to localhost:9000.
Those things are to be able to be changed from a SSH/SCP with a user that does not have root access, but has write access to pre-determined folders, where html pages and an executable which contains the FastCGI stuff & that will be auto-started, can be put.
So, the nginx configuration is not to be changed by that user.
There is a library to access special services running on the device, reading some sensors and stuff like that - which the custom FastCGI app can use to query things, and then display values via html page. There is also a need to e.g. change some device settings from the web browser on that served webpage.
Now, I have no idea of how a FastCGI C++ program actually interacts with the browser.
I played with the examples of the once official FCGI library, now without an own webpage, archived e.g. here: https://github.com/FastCGI-Archives/fcgi2
So, I can serve a generate html page from my C++ now in the way shown there.
But I have no idea of how to get values entered in the web browser to be processed in my C++ program.
So apparently, using a html form with a submit button would be a way to transmit data from client to server.
Reading @ W3C description of form action, it seems that t he action always refers to some URL, e.g. a html file, script, laying in the server.
Or, as the poster there showed, a location defined in the nginx config, in his case, /upload.
Now, the latter thing I want to avoid - nginx config shall not be changed by customizing the webpage behavior.
The former thing, adding extra script files to which the form action points, seems to defeat the purpose of having a C++ program that is supposed to do any active stuff.
I added a code section in my current C++ program that reads the input stream of a request - so far, there is nothing there, but I guess it's because nothing gets sent if I already get a 404 because I have no script that the action could point to
Is it possible to have a html page that sends stuff to my C++ app without any such extra scrips or nginx locations?
Edit:
I found a plugin for vscode: Thunder Client (a free alternative to Postman), which allows me to generate post or get requests and shows the reply.
If I do that, and add a query parameter with some text, the input stream of my FastCGI C++ app still has no input... I wonder whether I'm comletely misunderstanding something here.
The input stream reading is like here: in the lines 136 & 154. The html generated & sent in that example does turn up in the reply window of Thunder Client (albeit with "Standard Input - 0 bytes"), so generally, the setup works.
Edit #2:
Ok, so a generated query with Thunder Client, where I add e.g. "param1=hello" - this will actually end up in the environment var "QUERY_STRING", not in the input stream.
What kind of things do end up in the standard input stream?
Last edited by somanyquestions; 01-13-2023 at 11:03 AM.
(You'll certainly need a different, more appropriate IDE)
The FastCGI program interacts with the web server, not the browser. The web server receives a lump of text from the web browser formatted as HTTP, deals with it, and then sends a lump of text back to the web client,also formatted as HTTP. Transaction over.
Where FastCGI fits in is that your FastCGI program will stay running separately on its own and keep itself connected to a socket, either a UNIX socket or a TCP socket, your choice. The socket is usually set up by your web server, and in some configurations the program is even launched by the web server. However, even if you use another means to establish the socket or to launch the program, the web server must be configured to work with the socket. Then your program, or the library involved, waits and reads the stream of text from the socket and processes the HTTP headers and data included whenever they show up, then it writes out plain text in response which also contains some HTTP headers and data.
Keep in mind that HTTP itself is a stateless, text-based protocol.
The FastCGI program interacts with the web server, not the browser.
Am I interacting with you, or with my keyboard/screen setup?
Perhaps both, depending on the level of abstraction appropriate for the situation of interest
That's what I meant.
Quote:
Where FastCGI fits in is that your FastCGI program will stay running separately on its own and keep itself connected to a socket, either a UNIX socket or a TCP socket, your choice. The socket is usually set up by your web server
Yes, that was already working that far.
Thanks for the links, I found some details about e.g. the difference between GET and POST method there.
I meanwhile saw that some things are conveniently added to the query string, while other stuff gets put into the message body - which is what comes out of the input stream in the FCGI app.
What I wonder now:
The Thunder Client plugin has sub-tabs under the tab of Body for apparently common formats for body text, such as JSON.
Now, in fcgi official C++ examples, I saw, they always use the output stream to serve a generated HTML page.
So, if a request had JSON in its body, and, presumably, the response should contain JSON with some requested data in turn: in what way would that be served, and "who" would do such a query in the first place? I guess a mere static HTML page can't quite do that (sending JSON), and also, a response containing JSON with data, instead of a HTML page to display in the browser (as was the case in mentioned example code) - that's no useful food for the browser either.
So what is the actual usage scenario/constellation for this?
The essential idea behind "FastCGI" is that "the web-browser does not, itself, contain" the programming that is responsible for generating the final web-page output. Instead of doing this, e.g.mod_php, mod_perl, it packages and sends the request to a separate, third, layer of software. Which could of course be anywhere. When the FastCGI server's response is received, the Web server unpacks it and sends it back to the web client.
There are a number of advantages to this arrangement. The first, of course, is security: the Web server layer does not require "privileged access." But the second, equally or perhaps more important, is queueing. There is now an "elastic hose" between the request layer (#2) and the response layer (#3). If a "tsunami" of incoming requests happens, beyond the response layer's ability to handle it, some of those requests will be delayed – or, refused.
The "fourth-plus" layers to this scenario – database servers and so forth – are now insulated from any (intentional or unintentional) "tsunami," because they only accept requests from the "third layer," which is now equipped to regulate its own response to the queue of incoming requests.
Furthermore, the third layer is also now equipped to be "smart." Perhaps some types of requests should be given priority over others, and so on. Once you are dealing with a queue, you have options.
As for me, I always use the "FastCGI" strategy, in one form or another, when deploying web servers or services. I want the immediate-request-handling children of my web service processes to be "skinny," not "phat!"
---
FYI: In most programming systems, it is very straightforward to convert existing "mod-this-or-that" software systems to the "FastCGI" model without significant source-code changes.
Last edited by sundialsvcs; 01-18-2023 at 01:22 PM.
That all makes sense, thanks for highlighting that angle. Especially the filtering and prioritizing are relevant for what I intend to do, at some later point.
Btw, how would one discern different users communicating with the FastCGI C++ program simultaneously?
Looking at the output of the fcgi2 example "echo-cpp", what kind of info is in the "Request Environment" section, nothing there seems to be of help.
The remote IP is in there, but in my scenario, where there is a 2nd machine with also NGINX, reverse-proxying to the machine with the FastCGI program, the IP seen is always the same: from the proxying machine.
Last edited by somanyquestions; 01-18-2023 at 06:05 AM.
Btw, how would one discern different users communicating with the FastCGI C++ program simultaneously?
That's the stateless nature of HTTP there. Each request is new and has nothing to do with any previous connections, so tracking sessions is going to be a kind of Rube Goldberg contraption in code form.
In general, if you're going to try to track each session you'd have something unique such as session-specific data in a field passed by POST or GET or else maybe in a cookie. Cookies are once again considered rather problematic and even a faux pax. Therefore you might give stronger consideration to using GET or POST field, ideally with at least mild encryption so that it is hard to forge. It can be something as simple as a cryptographically signed session number, in base 36 or something else URL friendly if you use GET. There can be existing modules to address that, but they might also come with a lot of technical debt and general baggage.
Maybe websockets can be dragged into this, too.
Last edited by Turbocapitalist; 01-18-2023 at 06:06 AM.
I've seen by now that cookies for session ID seems to be popular, but needs extra work against "CSRF" attack... damn can of worms.
Quote:
something unique such as session-specific data in a field passed by POST or GET
How would that work if I can't check for some session-specific thing like a cookie being present vs. not, I mean, how would a session start?
Another little annoyance I stumbled over... anyone used Nginx (maybe not relevant) for this, using Unix Domain socket for FastCGI, and as so happens sometimes during development, kicked the FastCGI C++ app to put a newly compiled executable on the machine, start it again, and then get Error 404 in the browser? (also if I don't put a new exe on it, but works after reboot)
It seems to be related to the socket still being bound. Calling unlink() before FCGX_OpenSocket() didn't help, though.
Going back to localhost:port for now... but it seems unnecessary to involve network protocol stuff in the kernel for this.
Last edited by somanyquestions; 01-18-2023 at 11:45 AM.
Remember: "FastCGI" doesn't care about any of that. It is, very simply, "a matter of what the web-server process does next." And, what its role is, in what eventually transpires.
If you are using mod_, the web-server undertakes to handle the request itself ... which cannot withstand "denial-of-service tsunamis" and which requires the web-server to itself be "highly privileged." Whereas, if you are using FastCGI, it simply bundles-up the entire request and places it into a queue for someone else, somewhere else(it knows not where and cares not where ...), to somehow handle on its behalf. When the reply comes back, the web-server unpacks it and sends it on.
The "HTTP protocol" is unchanged. One way or the other, a web client submits a request and in due time gets a reply. But, with FastCGI, "the web server process is merely a clerk."
FYI: In many situations, the initial recipient of that request is also "a clerk." It must decide whether to refuse the request or to send it on to a worker-bee, and if so, which one. But, thisprocess, and its uniquely powerful role, is really the key to the whole thing. (But it is also possible to eliminate this step.)
Last edited by sundialsvcs; 01-18-2023 at 01:34 PM.
Remember: "FastCGI" doesn't care about any of that. It is, very simply, "a matter of what the web-server process does next." And, what its role is, in what eventually transpires.
FYI: In many situations, the initial recipient of that request is also "a clerk." It must decide whether to refuse the request or to send it on to a worker-bee, and if so, which one. But, thisprocess, and its uniquely powerful role, is really the key to the whole thing. (But it is also possible to eliminate this step.)
My problem here is that I don't see how, without using a cookie (or what ever mechanism to leave information at the client end), I'd have any means of discerning between different clients. I can tag as much funky information to GET or POST requests in my generated HTML, but I still have no means of telling by whom that was sent, when it arrives at the C++ server.
Or, at least, I'm not aware of it.
With a cookie, it seems obvious: If a request doesn't have one, I regard it as a new client/session and, say, create a new session ID and set a cookie with it. All next requests from that client will have that cookie & hence I know it's that client, until it expires or I tell the client to delete it, to end the session.
Opting to not use cookies, from my current n00b understanding of things, all I am seeing in my C++ app is incoming requests, and I have no idea by whom - so I also don't know what IDs or whatever to put in the response, so there's neither a chicken nor an egg I could start with for getting a session going.
Say, for example, your program produces and processes a web form or series of related web forms. One or more of the forms' fields can be dedicated to tracking the session. The program fills in the field with an identifier if it is either blank or invalid. It will be blank the first time a client connects. There after the subsequent forms' session field will carry that session information. POST or GET will not matter.
It's not complicated once you know how, the difficulty is getting past the reality that HTTP is stateless. If you are comfortable with Python, it is object oriented as C++ is, then you might sketch out a very, very simple session tracker using Flask to familiarize yourself with what's going on. Then it should be much easier to know what your C++ program will need to do.
"Cookies" are a very basic feature of the HTTP protocol, no matter how you implement the server – FastCGI or otherwise. This protocol is stateless. It therefore relies on "cookies" to distinguish the various requests and to associate them with host-side "sessions."
When a FastCGI web-server sends an incoming request to the back-end, everything is included, including all cookie names and values.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.