sdomi 3a454ca72a server: remove the goddamn tempfiles
this seems deliciously simple until you attempt it. we no longer do automatic
mimetype generation because it's *impossible* to do it for dynamic pages
without keeping a tempfile, or inventing time travel.

I tried splitting the fd's with tee, then using one to buffer the data,
and another to capture the mimetype. sadly, there's a circular dependency
between releasing and capturing data, so unless you're happy with your data
going straight to stdout, it's impossible to use fd's as they were intended.
also, if your fd's are cross-dependent on each other, you're gonna suffer.

what's up with the tail invocations? we need someone to "timeshift" our data;
tail has to block the I/O so the output doesn't leak out to stdout before we
print headers. it's waiting for 2GB of data which will (hopefully) never
happen. finger's crossed. anyways, once we're done with the headers, we
close the fd, which releases all the output to the socket. lastly, wait
is there to make sure we don't close the connection too early.
2026-04-29 20:49:56 +02:00
2026-04-19 19:06:38 +02:00
2020-11-06 00:36:08 +01:00
2026-04-29 20:49:56 +02:00
2021-09-09 18:35:45 +02:00
2021-05-16 11:10:39 +02:00
2021-03-09 18:57:10 +01:00
2025-04-02 22:37:33 +02:00
2026-04-16 01:08:21 +02:00
2024-12-23 19:36:03 +01:00
2025-11-09 01:15:55 +01:00

HTTP.sh

the coolest web framework (in Bash) to date.

We now have an IRC channel! Join #http.sh @ irc.libera.chat

Documentation

We have some guides and general documentation in the docs directory. Among them:

Dependencies

Absolutely necessary:

  • Bash (5.x, not interested in backwards compat)
  • either Ncat (not openbsd-nc, not netcat, not nc) or socat, or a combo of both
  • GNU grep/sed

Full list of dependencies: required, optional.

Known faults

  • if ncat fails to bind to [::], change the bind to 127.0.0.1 or 0 in config/master.sh
  • $post_multipart doesn't keep original names - could be fixed by parsing individual headers from the multipart request instead of skipping them all
  • websocket impl isn't properly finished
  • fails with an empty response, instead of throwing 400/500

Variables that we think are cool!

(this data may be slightly outdated. Full docs TODO.)

  • get_data - holds data from GET parameters
    • /?test=asdf -> ${get_data[test]} == "asdf"
  • params - holds parsed data from URL router
    • /profile/test (assuming profile/:name) -> ${params[name]} == "test"
  • post_data - same as above, but for urlencoded POST params
    • test=asdf -> ${post_data[test]} == "asdf"
  • post_multipart - contains paths to uploaded files from multipart/form-data POST requests. WARNING: it doesn't hold field names yet, it relies on upload order for identification
    • first file (in upload order) -> cat ${post_multipart[0]}
    • second file -> cat ${post_multipart[1]}
  • r - misc request data
    • authorization
    • content_boundary
    • content_boundary
    • content_length
    • content_type
    • headers
    • host
    • host_portless
    • ip
    • post
    • proto
    • status
    • uri
    • url
    • user_agent
    • view
    • websocket_key
  • cfg - server and app config - see config/master.sh for more details

Fun stuff

  • To prevent running malicious scripts, by default only scripts with extension .shs can be run by the server, but this can be changed in the config.
  • ${cfg[index]} ignores the above - see config/master.sh
  • Trans rights!
  • SHS stands for Shell Server.
Description
Cool shit
Readme 395 KiB
Languages
Shell 99.7%
Dockerfile 0.3%