15 ms·
Serving 200M requests per day with a CGI-bin
- eyberg 1y agoOutside of nostalgia there's no engineering reason to do this - definitely not for performance. That same go program can easily go over 10k reqs/sec without having to spawn a process for each incoming request. CGI is insanely slow and insanely insecure.
- simonw 1y agoWhat makes it insecure? It's a pretty simple protocol - anything in there that makes is insecure beyond naive mistakes that could be avoided with a well designed library? EDIT: Looks like the way CGI works made it vulnerable to Shellshock in 2014: https://en.m.wikipedia.org/wiki/Shellshock_(software_bug) https://en.m.wikipedia.org/wiki/Shellshock_(software_bug) I agree that there's probably not much of an argument to switch to it from the well established alternative mechanisms we are using already. The one thing in its favor is that it makes it easier to have a polyglot web app, with different languages used for different paths. You can get the same thing using a proxy server though.
- eyberg 1y agoCGI has a very long history of security issues stemming primarily from input validation or the lack thereof.
- simonw 1y agoRight, but anything relating to input validation can be avoided by using a well designed library rather than implementing the protocol directly.
- BirAdam 1y agoThe language in use often has input validation libraries. The failure of the programmer to use them is not the fault of CGI. Further, proper administration of the machine can mitigate file injection, database injection, etc. Again, that people fail to do this isn’t the fault of CGI.
- cranberryturkey 1y agoThat's like saying forks and knives are vulnerable becuase you could stab someone with them.
- deleted 1y ago[deleted]
- AdieuToLogic 1y ago> CGI has a very long history of security issues stemming primarily from input validation or the lack thereof. And a Go program reading from a network connection is immune from the same concerns how?
- nottorp 1y agoIt's not, you have to use Rust :)
- AdieuToLogic 1y ago> It's not, you have to use Rust :) If only I could borrow such confidence in network data... :-D
- tonyedgecombe 1y ago>EDIT: Looks like the way CGI works made it vulnerable to Shellshock in 2014: From your linked article: If the handler is a Bash script, or if it executes Bash... But we are talking about Python not Bash.
- kragen 1y agoYes, Shellshock is kind of a marginal case, but it probably does qualify as a security hole due in part to CGI itself, even though it doesn't affect Python programs (unless they spawn a shell). I don't know of any other examples of security problems caused by CGI, even partly. It's a very thin layer over HTTP.
- slashdave 1y agoBecause... it can execute an arbitrary executable? In the old days, it also ran as root.
- kragen 1y agoNo, on all the servers I have any experience with, it can only execute executables the server administrator configures as CGI programs, not executables supplied by an attacker, and they never ran as root. Apache in particular is universally run as a non-root user, since the very first release, and its suEXEC mechanism (used for running CGI programs as their owners for shared web hosting services) refuses to run any CGI program as root. I've never seen a web server on a Unix system running as root: not CERN httpd, not NCSA httpd, not Apache, not nginx, not python -m http.server, not any of the various web servers I've written myself. I hesitate to suggest that you might be misremembering things that happened 30 years ago, but possibly you were using a very nonstandard setup?
- rvnx 1y agoBusyBox runs as root by default, and it's used by hundreds of millions of devices. For embedded devices (routers, security cameras, etc), it's very common to run CGI scripts as root. So it is not even 30 years ago, it's still today, because of bad practices of the past.
- kragen 1y agoOh, that's a good point. In those cases the web server actually needs root, in the sense that it has to be able to upgrade the firmware and reconfigure the network interface.
- sitharus 1y agoIt definitely can’t. Either you had to put your script in cgi-bin, use an extension like .cgi in a directory with that feature explicitly enabled, or a magic sticky bit on the file if that was enabled. You could configure the server to be insecure by, eg, allowing cgi execution from a directory where uploaded files are stored.
- mike_hearn 1y agoIIRC the main issue was finding ways to convince a CGI script to write something to disk, at which point you could sometimes make it be treated as another CGI script. More of an issue on Windows than UNIX.
- cperciva 1y agoHey, it could be worse. Some people launch entire VMs to service individual requests.
- klysm 1y agoThat’s cloud-native!
- giantrobot 1y agoYou mean "Web Scale".
- jasonvorhe 1y agoHow is that done?
- cperciva 1y agoI was making a joke about AWS Lambda. It doesn't necessarily start up a new VM for each request, though; it can launch a new VM but it will reuse an existing VM if the same CGI-bin (oops I mean Lambda function) has been executed recently.
- whstl 1y agoYou're joking, but working in finance I witnessed the misuse of AWS Batch + AWS ECS to do something similar. Not gonna dox the company, but it was a German fintech unicorn. It wasn't exactly for serving the response of the request per se, but a single customer click would launch an AWS ECS container with the whole Ruby and Rails VM just to send a single email message, rather than using a standard job queue. It is extremely slow and super expensive. Amusingly, the UI had to be hardened so that double clicks don't cause two VMs to launch. The rationale was that they already had batch jobs running in ECS, so "why not use it for all async operations".
- kragen 1y agoI mean, a process kind of is an entire VM. But yeah, serverless is a marketing term for CGI scripts.
- __float 1y agoNot everything needs 10k RPS, and in some sense there are benefits to a new process – how many security incidents have been caused by accidental cross-request state sharing? And in a similar vein, Postgres (which is generally well liked!) uses a new backend process per connection. (Of course this has limitations, and sometimes necessitates pgbouncer, but not always.)
- Tractor8626 1y agoEven without pgbouncer postgres uses long lived connections (and long lived processes) . So bad example. Uber famously switched from pg to mysql because their SWEs couldn't properly manage connections
- anonzzzies 1y agoWas that the only reason? In our last testing (2021), on the same hardware and for our specific case (a billions of records database with many tables and specific workfloads), mysql consistently left postgres in the dust performance wise. Internal and external devs pointed out that probably postgres (or rather, our table structures & indexes) could be tweaked with quite a lot of work to be faster, but mysql performed well (for our purpose) even with some very naive options. I guess it depends on the case, but I cannot justify spending 1 cent (let alone far more as we have 100k+ tables) on something while something else is fast enough (by quite a margin) to begin with...
- reddec 1y agoFew years ago I felt the same and created trusted-cgi. However, through the years I learned: - yes, forks and in general processes are fast - yes, it saves memory and CPU on low load sites - yes, it’s simple protocol and can be used even in shell However, - splitting functions (mimic serverless) as different binaries/scripts creates mess of cross scripts communication - deployment is not that simple - security wise, you need to run manager as root and use unique users for each script or use cgroups (or at least chroot). At that moment the main question is why not use containers asis Also, compute wise, even huge Go app with hundreds endpoints can fit just few megabytes of RAM - there is no much sense to save so few memory. At worst - just create single binary and run on demand for different endpoints
- deleted 1y ago[deleted]
- simonw 1y agoAlso discussed yesterday: https://news.ycombinator.com/item?id=44464272 https://news.ycombinator.com/item?id=44464272
- petesergeant 1y ago> The nascent web community quickly learned that this was a bad idea, and invented technologies like PHP Well ackshually ... the technology here that was important was mod_php; PHP itself was no different to Perl in how it was run, but the design choice of mod_php as compared to mod_perl was why PHP scripts could just be dumped on the server and run fast, where you needed a small amount of thinking and magic to mod_perl working.
- simonw 1y agoRight, but mod_php was an early addition to the PHP ecosystem and quickly became the default way of deploying it - I believe the first version of the Apache module was for PHP/FI Version 2.0 in 1996: https://www.php.net/manual/phpfi2.php#module https://www.php.net/manual/phpfi2.php#module
- petesergeant 1y agoIt was indeed, and I spent much time wailing and gnashing my teeth as a Perl programmer that nothing similar existed in Perl.
- xnx 1y agoIndeed. Perl was better in many ways, but not in the one that mattered to its continued viability.
- AdieuToLogic 1y ago> It was indeed, and I spent much time wailing and gnashing my teeth as a Perl programmer that nothing similar existed in Perl. mod_perl2[0] provides the ability to incorporate Perl logic within Apache httpd, if not other web servers. I believe this is functionally equivalent to the cited PHP Apache module documentation: Running PHP/FI as an Apache module is the most efficient way of using the package. Running it as a module means that the PHP/FI functionality is combined with the Apache server's functionality in a single program. 0 - https://perl.apache.org/docs/2.0/index.html https://perl.apache.org/docs/2.0/index.html
- faizshah 1y agoI’ve also thought about this moreso as part of a workflow for quickly prototyping stuff. At least for a lot of the modern JIT languages I believe their startup times will be dominated by your imports unless you go with a fastcgi model. This came up as I started adopting h2o web server for local scripts since it has clean and quick to write config files with mruby and fast-cgi handlers and is also crazy fast: https://h2o.examp1e.net/configure/fastcgi_directives.html https://h2o.examp1e.net/configure/fastcgi_directives.html Another place this can be useful is for allowing customers to extend a local software with their own custom code. So instead of having to use say MCP to extend your AI tool they can just implement a certain request structure via CGI.
- zokier 1y agoFastcgi kinda loses all the benefits of cgi though.
- dolmen 1y agoAn MCP frontend to CGI programs would not be a bad idea for a end user environment. This makes me wonder if an MCP service couldn't be also implemented as CGI: an MCP framework might expose its feature as a program that supports both execution modes. I have to dig into the specs.
- aaronblohowiak 1y agoEhhhhhhh. I believe but cannot cite that fork() got a lot cheaper over the last 30 years as well (independent of machine stats, I believe the Linux impl is inherently cheaper now but I can’t remember the details.) cgi bin works really well if you don’t have to pay for ssl or tcp connections to databases or other services, but you can maybe run something like istio if you need that. I have long thought that (fast)cgi is better model than proprietary “lambda” /“faas”. But the languages de jure and vendor lock in didn’t favor a standards based approach here.
- seabrookmx 1y agoYou should check out OpenFaaS. It uses a very CGI-inspired architecture for self hosting "functions" (in the lambda sense) on more conventional infra.
- AdieuToLogic 1y ago> I believe but cannot cite that fork() got a lot cheaper over the last 30 years as well ... The fork[0] system call has been a relatively quick operation for the entirety of its existence. Where latency is introduced is in the canonical use of the execve[1] equivalent in newly created child process. > ... cgi bin works really well if you don’t have to pay for ssl or tcp connections to databases or other services, but you can maybe run something like istio if you need that. Istio[2] is specific to Kubernetes and thus unrelated to CGI. 0 - https://man.freebsd.org/cgi/man.cgi?query=fork&apropos=0&sektion=0&manpath=FreeBSD+14.3-RELEASE+and+Ports&arch=default&format=html https://man.freebsd.org/cgi/man.cgi?query=fork&apropos=0&sek... 1 - https://man.freebsd.org/cgi/man.cgi?query=execve&sektion=2&apropos=0&manpath=FreeBSD+14.3-RELEASE+and+Ports https://man.freebsd.org/cgi/man.cgi?query=execve&sektion=2&a... 2 - https://istio.io/ https://istio.io/
- colesantiago 1y agodupe: https://news.ycombinator.com/item?id=44464272 https://news.ycombinator.com/item?id=44464272
- kragen 1y agoEven with things like Python, CGI is pretty fast these days. If your CGI script takes a generous 400 milliseconds of CPU to start up and your server has 64 cores, you can serve 160 requests per second, which is 14 million hits per day per server. That's a high-traffic site. That is, if your web service struggles to handle single-digit millions of requests per day, not counting static "assets", CGI process startup is not the bottleneck. A few years ago I would have said, "and of course it's boring technology that's been supported in the Python standard library forever," but apparently the remaining Python maintainers are the ones who think that code stability and backwards compatibility with boring technology are actively harmful things, so they've been removing modules from the standard library if they are too boring and stable. I swear I am not making this up. The cgi module is removed in 3.13. I'm still in the habit of using Python for prototyping, since I've been using it daily for most of the past 25 years, but now I regret that. I'm kind of torn between JS and Lua.
- simonw 1y agoHere's the justification for removing cgi - https://peps.python.org/pep-0594/#cgi https://peps.python.org/pep-0594/#cgi Amusingly that links to https://peps.python.org/pep-0206/ https://peps.python.org/pep-0206/ from 14th July 2000 (25 years ago!) which, even back then, described the cgi package as "designed poorly and are now near-impossible to fix". Looks like the https://github.com/jackrosenthal/legacy-cgi https://github.com/jackrosenthal/legacy-cgi package provides a drop-in replacement for the standard library module.
- kragen 1y agoThat fails pretty hard at providing a rationale. Basically it says that CGI is an inefficient interface because it involves creating a new process! Even if that were true, "You shouldn't want to do such an inefficient thing" is very, very rarely a reasonable answer to a technical question like "How do I write a CGI script in Python?" or "How do I parse a CSV file in Python?" There are certainly some suboptimal design choices in the cgi module's calling interface, things you did a much better job of in Django, but what made them "near-impossible to fix" was that at the time everyone reading and writing PEPs considered backwards compatibility to be not a bad thing, or even a mildly good thing, but an essential thing that was worth putting up with pain for. Fixing a badly designed interface is easy if you know what it should look like and aren't constrained by backwards compatibility.
- slashdave 1y agoMaybe my memory is bad, but I don't remember people jumping ship from CGI-bin because of performance. I do remember a lot of security problems.
- kragen 1y agoI remember performance being the main reason people jumped ship from CGI in the period 01995–02002. The switch didn't solve security problems itself (except Shellshock, if you wrote CGI scripts in bash, but Shellshock wasn't publicly known until much later) but it sometimes came with a less slapdash approach to building web services which did solve security problems. On the other hand, it often instead came with a move to PHP, which had just unbelievable levels of security problems. It's possible that your experience with people switching was later, when performance was no longer such a pressing concern.
- sitharus 1y agoThe main security issue I recall from CGI was caused by the web server having to execute the binary. This meant either executing as www-data, running the web server as root so it can call setuid, or using setuid binaries which have their own issues. These were real issues on multi-user hosts, but as most of the time we don’t use shared hosting like that anymore it’s not an issue. There were also some problems with libraries parsing the environment variables with the request data wrong, but that’s no different from a badly implemented http stack these days. I vaguely recall some issues with excessively log requests overflowing environment variables, but I can’t remember if that was a security problem or DoS.
- sramsay 1y agoI remember megatons of Java Servlet(tm) hype convincing us that real programmers do OO. Java remains the only programming language I've ever heard covered in a feature story for NPR.
- cb321 1y agoYeah. I mentioned this the other day: https://news.ycombinator.com/item?id=44466245 https://news.ycombinator.com/item?id=44466245 Combined with the dot-com boom "general hype", I'm sure a lot of managers pushed heavyweight solutions where lightweight would have sufficed. Well, that may be an eternal problem, but maybe more succeeded in pushing them with a lot of hype. :-) Not enough people I guess saw this as Sun trying to be the new Microsoft (which was the new IBM, which still has MVS & Cobol!), namely the company in control of The Platform, where here "The" just means the hip new thing kids learn in school and want to continue doing before they become expensive old timers.
- petesergeant 1y agoTangentially related, I wrote a brief history of CGI and the evolution away from it here (as conference slides): "A brief, incomplete and largely inaccurate history of dynamic webpages" https://www.slideshare.net/slideshow/psgi-and-plack-from-first-principles-49147547/49147547#4 https://www.slideshare.net/slideshow/psgi-and-plack-from-fir...
- Tractor8626 1y ago2400 rps on this hardware on hello world application - isn't it kinda bad? And we trading performance for what exactly? Code certainly didn't become any simpler.
- slyall 1y agoIt's only bad if you need to get more than 2000 rps Which is only a small proportion of sites out there.
- kqr 1y agoI'd argue it's bad even if you get more than 1000 Bq of requests. You never want to approach 100 % utilisation, and I'd aim to stay clear of 50 %.
- Tractor8626 1y agoIf there is no some other advantages - it is just bad.
- kragen 1y agoIt's boring technology that's supported everywhere, and starting the program from the beginning for every request eliminates a lot of the places where corrupted state can persist from one request to the next.
- gred 1y agoI'd rather not pay for 8 cores / 16 threads, though...
- withinboredom 1y agoDepends on where you are shopping. I pay €211 every month for 96 threads and 384 gb of ram (clustered) -- disks are small (around 1tb each), but I'm still nowhere near 50% utilization there.
- jarofgreen 1y agoHad a similar chat with someone recently after I used Apache for a side project in part because of it's .htaccess feature. This let's you drop .htaccess files anywhere and Apache will load them on each request for additional server config. https://httpd.apache.org/docs/2.4/howto/htaccess.html https://httpd.apache.org/docs/2.4/howto/htaccess.html One big reason to avoid them was performance; it required extra disk access on every request and it was always better to put the configuration in the main config file if possible. But now? When most servers have an SSD and probably spare RAM that Linux will use to cache the file system? Ok, performance is still slightly worse as Apache has to parse the config on every request as opposed to once, but again, now that most servers have more powerfull CPU's? In many use cases you can live with that. [ Side project is very early version but I'm already using it: https://github.com/StaticPatch/StaticPatch/tree/main https://github.com/StaticPatch/StaticPatch/tree/main ]
- rollcat 1y agoQuoting Rasmus Lerdorf: > I'm not a real programmer. I throw together things until it works then I move on. The real programmers will say "Yeah it works but you're leaking memory everywhere. Perhaps we should fix that." I’ll just restart Apache every 10 requests. PHP got a very long way since then, but a huge part of that was correcting the early mistakes. > PHP 8 is significantly better because it contains a lot less of my code.
- jarofgreen 1y agoI'm not sure in which spirit you mean that, so I'm going to choose "approvingly" :-) I do have thoughts for later about modes which could take all the config from .htaccess files and build them into the main config so then you avoid any performance issues - however you have to do that carefully to make sure people don't include any bad config that crashes the whole server. One of the nice things about using .htaccess files as intended is Apache has the Nonfatal flag on AllowOverride so you can avoid that. https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride https://httpd.apache.org/docs/2.4/mod/core.html#allowoverrid...
- 1y ago
- jekwoooooe 1y agoBut why? A lot of modern stacks aren’t just about performance but development speed and stuff
- WhereIsTheTruth 1y ago"Just pump more HW at the problem bro"
- ivovk 1y agoIt stops working when you need to connect to any external resource. Database, http clients etc maintain connection pools to skip initial connection phase, which can be costly. That’s why you usually need a running web application process
- ben0x539 1y agoAt my last job, a lot of our web services also benefited immensely from in-process caches and batching (to be fair, some of them were the cache for downstream services), and their scaling requirements pretty much dominated our budget. I can totally see how the cgi-bin process-per-request model is viable in a lot of places, but when it isn't, the difference can be vast. I don't think we'd have benefited from the easier concurrency either, but that's probably just because it was all golang to begin with.
- 8organicbits 1y agoYou can solve that with a sidecar, a dedicated process (or container) that pools connections for you. Pgbouncer as one example.
- rvnx 1y agoGreat, additional things to maintain that can break, all of that to work around the original sandcastle instead of fixing the root issue
- phplovesong 1y agoThe way "old" stacks like PHP work also makes it impossible to do stateful stuff, like websockets. There is work-arounds but usually it a better idea to ditch PHP for a better technology more suited for modern web.
- johnisgood 1y agoBetter technology? Please, do tell. And for your information, you can have stateful whatnots in PHP. Hell, you can have it in CSS as I have demonstrated in my earlier comments.
- phplovesong 1y agoI mean something that has a "running program" is a good start. Makes it trivial to do long lived stuff, like websockets.
- deleted 1y ago[deleted]
- gvalkov 1y agoWe're still serving a cgi-bin directory at work for the occasional quick and dirty internal web app. The ergonomics are great as long as you keep it simple. The fact that it's cgi doesn't mean you have to print http/1.0 to stdout manually. For example, in python the builtin wsgiref.handlers.CGIHandler lets you run any wsgi app as a cgi script: import wsgiref.handlers, flask app = flask.Flask(__name__) wsgiref.handlers.CGIHandler().run(app) The way we run the scripts is with uwsgi and its cgi plugin[1]. I find it simpler and more flexible than running apache or lighttpd just for mod_cgi. Since uwsgi runs as a systemd unit, we also have all of systemd's hardening and sandboxing capabilities at our disposal. Something very convenient in uwsgi's cgi handling that's missing from mod_cgi, is the ability to set the interpreter for a given file type: cgi = /cgi-bin=/webapps/cgi-bin/src cgi-allowed-ext = .py cgi-helper = .py=/webapps/cgi-bin/venv/bin/python3 # all dependencies go here Time to first byte is 250-350ms, which is acceptable for our use case. [1]: https://uwsgi-docs.readthedocs.io/en/latest/CGI.html https://uwsgi-docs.readthedocs.io/en/latest/CGI.html
- kragen 1y agoThis is great information, thanks! And it looks like wsgiref.handlers.CGIHandler isn't deprecated yet.
- johnisgood 1y agoI remember when I used a C program with CGI. It was quite fast, and this was decades ago. There were no >100 cores or threads, and RAM was not abundant either, it was at best 1 GB. It was doable then, pretty sure it is even more doable today.
- PaulDavisThe1st 1y agoAmazon in 1995 was a C++ executable invoked via CGI () That couldn't scale once load-balancing was required, but it worked pretty well up until that point. () technically, two of them: one handled the front (customer visible) end, one handled the back-office side.
- kragen 1y agoOh right! And then you moved to ISAPI, right?
- PaulDavisThe1st 1y agoNo idea, I was gone.
- kragen 1y agoOh, I hadn't realized you'd left so early.
- indigodaddy 1y agoSpeaking of old stuff like newspro, anyone remember php scripts like CuteNews and sNews (single file CMS) ?
- doublerabbit 1y agoYes, CuteNews was clever. PHPNuke, e107, all those happy days downloading source files on 56K and uploading them to my webhost to play with.
- indigodaddy 1y agoSome super fun times for sure and the scene is not easily replicated by anything today
- reidrac 1y agoIf the cgi bin needs DB access, every time the process starts it needs to open a connection. Having the code in memory, for example using fastcgi, is not only to avoid the startup time penalty; you can also have a DB connection pool or at least a persistent DB connection per thread.
- procaryote 1y agoDo it at scale and your database will be sad about the number of connections At least that was the case when I did the "python is single threaded, let's run many of them" + "python is slow, let's run many of them" dance At scale you end up using shared connection pools outside of python (like pgbouncer) and a lot of tuning to make it serve the load while not killing the database Of course, then we reimplemented in a multithreaded somewhat performant language and it became dead simple again
- Twirrim 1y agoThere were standard ways to handle that, such as hosting a separate daemon that acts effectively as your proxy. Using Unix sockets instead of TCP/IP makes connecting to it relatively cheap.
- Iwan-Zotow 1y agoUse udp
- pjmlp 1y agoThat is why CGI eventually evolved into a model that would keep some of the stuff around between requests.
- genghisjahn 1y agoI recently ran a test where I had a $350 mini server using a golang binary, rabbitmq, redis and MySQL (all hosted on the same mini server)handle 5000 reqs/s sustained. That translates to 400 million reqs in a 24 hour day. I’m amazed at how great the tools are these days that are free and yet we pay so much to cloud providers. I know it’s not an apples to apples comparison but it was so great to develop all that and fine tune it on a box in my basement.
- jgalt212 1y agoIndeed. When I look at our VM spend, it's high because we need servers with a lot of local disk--not a lot of compute. For some reason, you cannot get one without the other. Can you imagine the size of the business / service you could run with 4 attached 20TB drives, and a modest CPU? Good luck getting such from a cloud provider.
- 0xbadcafebee 1y agoEven in the early 2000s CGI was really old tech. People were moving to more modern systems that solved the problems with CGI. What's funny is, modern systems actually have exactly the same problems as some of those newer solutions, yet they're just ignored/accepted now? In the mid-2000s I worked on a very-large-scale website using Apache2 w/mod_perl. Our high-traffic peaks were something like 25k RPS (for dynamic content; total RPS was >250k). Even at that time it was a bit old hat, but the design scaled very well. You'd have a fleet of mod_perl servers that would handle dynamic content requests, and a fleet of Apache2 servers that served static content and reverse-proxied back to the mod_perl fleet for dynamic requests. In front of the static servers were load balancers. They'd all keep connection pools open and the load balancers avoided the "maximum connection limit" of typical TCP/IP software, so there was no real connection limit, it was just network, memory, and cpu limits. The big benefit of Apache2 w/mod_perl or mod_php was that you combined the pluggability and features of a scalable and feature-filled web server with the resident memory and cache of an interpreter that didn't need to keep exiting and starting. Yes you had to do more work to integrate with it, but you have to do that today with any framework. The big downside was bugs. If you had a bug, you might have to debug both Apache and your application at the same time. There was not as much memory to be had, so memory leaks were a MUCH bigger problem than they are today. We worked around it with stupid fixes like stopping interpreters after taking 1000 requests or something. The high-level programmers (Perl, PHP) didn't really know C or systems programming so they didn't really know how to debug Apache or the larger OS problems, which it turns out has not changed in 20 years... FastCGI and later systems had the benefit that you could run the same architecture without being tied to a webserver and dealing with its bugs on top of your own. But it also had the downside of (in some cases) not multiplexing connections, and you didn't get tight integration with the web server so that made some things more difficult. Ultimately every backend web technology is just a rehashing of CGI, in a format incompatible with everything else. There were technical reasons why things like FastCGI, WSGI, etc exist, but today they are unnecessary now that we have HTTP/2 and HTTP/3. If you can multiplex HTTP connections and serve HTTP responses, you don't need anything else. I really hope future devs will stop reinventing the wheel and go back to actual standards that work outside your own single application/language/framework.
- pvtmert 1y agoTo me, the `inetd` _is_ the CGI. Which made internet waay more fun. I, myself hosted various shell scripts through inetd, even an HTTP one which was written completely in Bash. Although the VPS is long gone, and I did not use any version control at the time. The laptop I wrote the stuff are gone too :'(. But it was certainly quite fun. Deployment was as easy as Makefile + scp and testing was the another Bash script with bunch of `netcat`s and greps. What a time to be alive :)
- vivzkestrel 1y agocan anyone with expertise in CGI actually shed some light on what problems do CGIs actually have? like why did we hop from this to React?
- zh3 1y agoThe oft-cited reason is each call fires up a new process so is expensive in terms of resources (though resources are cheap these days). Additionally, the CGI program has to faff about to retrieve data and parameters from the request (easy to get wrong) plus you have to watch out for security issues (hard to get right). Plus, of course, since the process exits at the end of the request any kind of session tracking needs to implemented separately. Having said, for inhouse use, embedded and/or trusted environments they allow super quick hacks, e.g. complete CGI 'program' to print the date (put it in cgi-bin and make it executable):- #!/bin/sh echo "Context-Type: text/plain\r\n" echo "Your IP is $REMOTE_ADDR" date
- vivzkestrel 1y agois there a benchmark that you are aware of that takes a cgi program and pits it against modern frameworks like node.js express , hono etc? just to get a feel of how many requests will be handled at scale
- zh3 1y agoNo, though there are many articles proving X is faster than Y along with articles proving the opposite. The process overhead is likely to hurt CGI though, which is why FastCGI was developed. As covered elsewhere in the thread, having a fast front end with effective comms to a well-written backend seems a reasonably sweet spot.
- deleted 1y ago[deleted]
- Sami_Lehtinen 1y agoFor CGI endpoints that are called infrequently—daily, weekly, or even monthly—the script startup delay is negligible. Even a persistent process waiting to handle a request can have its memory swapped to disk by the OS under varying server load. When a request finally arrives, the delay from swapping that memory back in can negate any theoretical advantage over a cold-starting CGI script.