Showing posts from July, 2021

HTTP server in Ruby 3 - Fibers & Ractors

This is part #2. Head over to part #1 to learn about HTTP in Ruby. Motivation Historically Ruby's been lacking in the concurrency department. Ruby has "native" threads (prior to 1.9 there were only "green"), which means there can be multiple threads controlled by an OS, but only 1 thread can be executed at a time, this is managed via Global Interpreter Lock (GIL). However, native calls and I/O calls can be executed in parallel. During an I/O call, a thread gives up control and waits for a signal that the I/O has finished. This means I/O heavy applications can benefit from multiple threads. In this article we are going to explore different concurrency modes for our HTTP server: Single-threaded Multi-threaded Fibers Ractors Single-threaded Let's start simple and see how a single threaded HTTP server could look like ( full code ): def start socket =, PORT) sock

Ruby HTTP server from the ground up

Getting something to work quickly is important when you are starting out, but if you want to become better at programming it's important to know a few levels below the abstractions you are used to be working with. When it comes to Web development it's important to know how HTTP works, and what better way to do that than go through baptism by fire and build our own HTTP server. How does HTTP look anyway? HTTP is plaintext protocol implemented over TCP so we can easily inspect what requests look like ( HTTP 2 is actually no longer plaintext, it's binary for efficiency purposes ). One way to look at request structure is to use curl with -v (verbose) flag: curl -H "x-some-header: value" -v Outputs GET /something HTTP/1.1 Host: User-Agent: curl/7.64.1 Accept: */* x-some-header: value And in response we get HTTP/1.1 404 Not Found Age: 442736 Cache-Control: max-age=604800 Content-Type: