diff --git a/ruby-server-example/.gitignore b/ruby-server-example/.gitignore new file mode 100644 index 0000000..8871566 --- /dev/null +++ b/ruby-server-example/.gitignore @@ -0,0 +1,2 @@ + +bsf-result/ \ No newline at end of file diff --git a/ruby-server-example/Dockerfile b/ruby-server-example/Dockerfile new file mode 100644 index 0000000..f176991 --- /dev/null +++ b/ruby-server-example/Dockerfile @@ -0,0 +1,19 @@ +FROM ttl.sh/ruby-base:dev AS build + +WORKDIR /src + +COPY . . + +RUN apk add --no-cache build-base libxml2-dev libxslt-dev tzdata. + +FROM ttl.sh/ruby-base:runtime AS final + +WORKDIR /src + +COPY Gemfile Gemfile.lock /src/ + +COPY . /src + +EXPOSE 9898 + +CMD ["ruby", "main.rb"] \ No newline at end of file diff --git a/ruby-server-example/Gemfile b/ruby-server-example/Gemfile new file mode 100644 index 0000000..4c89ade --- /dev/null +++ b/ruby-server-example/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'activesupport', '~> 7.0' \ No newline at end of file diff --git a/ruby-server-example/bsf.hcl b/ruby-server-example/bsf.hcl new file mode 100644 index 0000000..f6b2146 --- /dev/null +++ b/ruby-server-example/bsf.hcl @@ -0,0 +1,27 @@ + +packages { + development = ["coreutils-full@9.5", "bash@5.2.15", "ruby@~3.1.2"] + runtime = ["cacert@3.95"] +} + +oci "build" { + name = "ttl.sh/ruby-base" + layers = ["split(packages.runtime)", "split(packages.dev)"] + isBase = true + cmd = [] + entrypoint = [] + envVars = [] + exposedPorts = [] + importConfigs = [] +} + +oci "runtime" { + name = "ttl.sh/ruby-base" + layers = ["split(packages.runtime)"] + isBase = true + cmd = [] + entrypoint = [] + envVars = [] + exposedPorts = [] + importConfigs = [] +} diff --git a/ruby-server-example/bsf.lock b/ruby-server-example/bsf.lock new file mode 100644 index 0000000..8f1de1f --- /dev/null +++ b/ruby-server-example/bsf.lock @@ -0,0 +1,305 @@ +{ + "app": { + "name": "" + }, + "packages": [ + { + "package": { + "name": "bash", + "revision": "1ebb7d7bba2953a4223956cfb5f068b0095f84a7", + "version": "5.2.15", + "description": "GNU Bourne-Again Shell, the de facto standard shell on Linux", + "homepage": "https://www.gnu.org/software/bash", + "free": true, + "spdx_id": "GPL-3.0-or-later", + "epoch_seconds": 1653393815, + "platforms": [ + "i686-cygwin", + "x86_64-cygwin", + "x86_64-darwin", + "i686-darwin", + "aarch64-darwin", + "armv7a-darwin", + "i686-freebsd13", + "x86_64-freebsd13", + "x86_64-solaris", + "aarch64-linux", + "armv5tel-linux", + "armv6l-linux", + "armv7a-linux", + "armv7l-linux", + "i686-linux", + "loongarch64-linux", + "m68k-linux", + "microblaze-linux", + "microblazeel-linux", + "mips-linux", + "mips64-linux", + "mips64el-linux", + "mipsel-linux", + "powerpc64-linux", + "powerpc64le-linux", + "riscv32-linux", + "riscv64-linux", + "s390-linux", + "s390x-linux", + "x86_64-linux", + "aarch64-netbsd", + "armv6l-netbsd", + "armv7a-netbsd", + "armv7l-netbsd", + "i686-netbsd", + "m68k-netbsd", + "mipsel-netbsd", + "powerpc-netbsd", + "riscv32-netbsd", + "riscv64-netbsd", + "x86_64-netbsd", + "i686-openbsd", + "x86_64-openbsd", + "x86_64-redox" + ] + }, + "runtime": false + }, + { + "package": { + "name": "cacert", + "revision": "ac5c1886fd9fe49748d7ab80accc4c847481df14", + "version": "3.95", + "description": "A bundle of X.509 certificates of public Certificate Authorities (CA)", + "homepage": "https://curl.haxx.se/docs/caextract.html", + "free": true, + "spdx_id": "MPL-2.0", + "epoch_seconds": 1699289668, + "platforms": [ + "i686-cygwin", + "x86_64-cygwin", + "x86_64-darwin", + "i686-darwin", + "aarch64-darwin", + "armv7a-darwin", + "i686-freebsd13", + "x86_64-freebsd13", + "aarch64-genode", + "i686-genode", + "x86_64-genode", + "x86_64-solaris", + "javascript-ghcjs", + "aarch64-linux", + "armv5tel-linux", + "armv6l-linux", + "armv7a-linux", + "armv7l-linux", + "i686-linux", + "loongarch64-linux", + "m68k-linux", + "microblaze-linux", + "microblazeel-linux", + "mips-linux", + "mips64-linux", + "mips64el-linux", + "mipsel-linux", + "powerpc64-linux", + "powerpc64le-linux", + "riscv32-linux", + "riscv64-linux", + "s390-linux", + "s390x-linux", + "x86_64-linux", + "mmix-mmixware", + "aarch64-netbsd", + "armv6l-netbsd", + "armv7a-netbsd", + "armv7l-netbsd", + "i686-netbsd", + "m68k-netbsd", + "mipsel-netbsd", + "powerpc-netbsd", + "riscv32-netbsd", + "riscv64-netbsd", + "x86_64-netbsd", + "aarch64_be-none", + "aarch64-none", + "arm-none", + "armv6l-none", + "avr-none", + "i686-none", + "microblaze-none", + "microblazeel-none", + "mips-none", + "mips64-none", + "msp430-none", + "or1k-none", + "m68k-none", + "powerpc-none", + "powerpcle-none", + "riscv32-none", + "riscv64-none", + "rx-none", + "s390-none", + "s390x-none", + "vc4-none", + "x86_64-none", + "i686-openbsd", + "x86_64-openbsd", + "x86_64-redox", + "wasm64-wasi", + "wasm32-wasi", + "x86_64-windows", + "i686-windows" + ] + }, + "runtime": true + }, + { + "package": { + "name": "coreutils-full", + "revision": "7445ccd775d8b892fc56448d17345443a05f7fb4", + "version": "9.5", + "description": "The GNU Core Utilities", + "homepage": "https://www.gnu.org/software/coreutils/", + "free": true, + "spdx_id": "GPL-3.0-or-later", + "epoch_seconds": 1716993062, + "platforms": [ + "i686-cygwin", + "x86_64-cygwin", + "x86_64-darwin", + "i686-darwin", + "aarch64-darwin", + "armv7a-darwin", + "i686-freebsd", + "x86_64-freebsd", + "x86_64-solaris", + "aarch64-linux", + "armv5tel-linux", + "armv6l-linux", + "armv7a-linux", + "armv7l-linux", + "i686-linux", + "loongarch64-linux", + "m68k-linux", + "microblaze-linux", + "microblazeel-linux", + "mips-linux", + "mips64-linux", + "mips64el-linux", + "mipsel-linux", + "powerpc64-linux", + "powerpc64le-linux", + "riscv32-linux", + "riscv64-linux", + "s390-linux", + "s390x-linux", + "x86_64-linux", + "aarch64-netbsd", + "armv6l-netbsd", + "armv7a-netbsd", + "armv7l-netbsd", + "i686-netbsd", + "m68k-netbsd", + "mipsel-netbsd", + "powerpc-netbsd", + "riscv32-netbsd", + "riscv64-netbsd", + "x86_64-netbsd", + "i686-openbsd", + "x86_64-openbsd", + "x86_64-redox", + "i686-cygwin", + "x86_64-cygwin", + "x86_64-windows", + "i686-windows" + ], + "attr_name": "coreutils-full" + }, + "runtime": false + }, + { + "package": { + "name": "ruby", + "revision": "4a6ce1efede1f89a857e0cc514d5d11e56621527", + "version": "3.1.2", + "description": "An object-oriented language for quick and easy programming", + "homepage": "https://www.ruby-lang.org/", + "free": true, + "spdx_id": "Ruby", + "epoch_seconds": 1676610054, + "platforms": [ + "i686-cygwin", + "x86_64-cygwin", + "x86_64-darwin", + "i686-darwin", + "aarch64-darwin", + "armv7a-darwin", + "i686-freebsd13", + "x86_64-freebsd13", + "aarch64-genode", + "i686-genode", + "x86_64-genode", + "x86_64-solaris", + "js-ghcjs", + "aarch64-linux", + "armv5tel-linux", + "armv6l-linux", + "armv7a-linux", + "armv7l-linux", + "i686-linux", + "m68k-linux", + "microblaze-linux", + "microblazeel-linux", + "mipsel-linux", + "mips64el-linux", + "powerpc64-linux", + "powerpc64le-linux", + "riscv32-linux", + "riscv64-linux", + "s390-linux", + "s390x-linux", + "x86_64-linux", + "mmix-mmixware", + "aarch64-netbsd", + "armv6l-netbsd", + "armv7a-netbsd", + "armv7l-netbsd", + "i686-netbsd", + "m68k-netbsd", + "mipsel-netbsd", + "powerpc-netbsd", + "riscv32-netbsd", + "riscv64-netbsd", + "x86_64-netbsd", + "aarch64_be-none", + "aarch64-none", + "arm-none", + "armv6l-none", + "avr-none", + "i686-none", + "microblaze-none", + "microblazeel-none", + "msp430-none", + "or1k-none", + "m68k-none", + "powerpc-none", + "powerpcle-none", + "riscv32-none", + "riscv64-none", + "rx-none", + "s390-none", + "s390x-none", + "vc4-none", + "x86_64-none", + "i686-openbsd", + "x86_64-openbsd", + "x86_64-redox", + "wasm64-wasi", + "wasm32-wasi", + "x86_64-windows", + "i686-windows" + ] + }, + "runtime": false + } + ] +} \ No newline at end of file diff --git a/ruby-server-example/bsf/default.nix b/ruby-server-example/bsf/default.nix new file mode 100755 index 0000000..e69de29 diff --git a/ruby-server-example/bsf/flake.lock b/ruby-server-example/bsf/flake.lock new file mode 100755 index 0000000..83663ca --- /dev/null +++ b/ruby-server-example/bsf/flake.lock @@ -0,0 +1,163 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix2container": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1730479402, + "narHash": "sha256-79NLeNjpCa4mSasmFsE3QA6obURezF0TUO5Pm+1daog=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "5fb215a1564baa74ce04ad7f903d94ad6617e17a", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1712920918, + "narHash": "sha256-1yxFvUcJfUphK9V91KufIQom7gCsztza0H4Rz2VCWUU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "92323443a56f4e9fc4e4b712e3119f66d0969297", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7": { + "locked": { + "lastModified": 1702939464, + "narHash": "sha256-mZqoH5fXxh8UxjUKpqi09UBXEPpz4w+2Ef0AVTLuF+g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1ebb7d7bba2953a4223956cfb5f068b0095f84a7", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1ebb7d7bba2953a4223956cfb5f068b0095f84a7", + "type": "github" + } + }, + "nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527": { + "locked": { + "lastModified": 1699307591, + "narHash": "sha256-BcAbJ57F4h449MLw8P35R1aU6iFuhhWLz9I9VtSk9IM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "4a6ce1efede1f89a857e0cc514d5d11e56621527", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "4a6ce1efede1f89a857e0cc514d5d11e56621527", + "type": "github" + } + }, + "nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4": { + "locked": { + "lastModified": 1716993062, + "narHash": "sha256-Q7+8FPD2V8OoGAe0d5LoE8HZ5KYJMyb80klPyrZj2hw=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "7445ccd775d8b892fc56448d17345443a05f7fb4", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "7445ccd775d8b892fc56448d17345443a05f7fb4", + "type": "github" + } + }, + "nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14": { + "locked": { + "lastModified": 1702838883, + "narHash": "sha256-R01Ga1NsBsZsNkLrnhuw+6gJIKtz9B15L9vybTlLpko=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ac5c1886fd9fe49748d7ab80accc4c847481df14", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ac5c1886fd9fe49748d7ab80accc4c847481df14", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1731676054, + "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nix2container": "nix2container", + "nixpkgs": "nixpkgs_2", + "nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7": "nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7", + "nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527": "nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527", + "nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4": "nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4", + "nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14": "nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/ruby-server-example/bsf/flake.nix b/ruby-server-example/bsf/flake.nix new file mode 100755 index 0000000..6bfaa6e --- /dev/null +++ b/ruby-server-example/bsf/flake.nix @@ -0,0 +1,191 @@ + +{ + description = ""; + + inputs = { + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14.url = "github:nixos/nixpkgs/ac5c1886fd9fe49748d7ab80accc4c847481df14"; + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4.url = "github:nixos/nixpkgs/7445ccd775d8b892fc56448d17345443a05f7fb4"; + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527.url = "github:nixos/nixpkgs/4a6ce1efede1f89a857e0cc514d5d11e56621527"; + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7.url = "github:nixos/nixpkgs/1ebb7d7bba2953a4223956cfb5f068b0095f84a7"; + + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + + + + + + + + + + nix2container.url = "github:nlewo/nix2container"; + }; + + outputs = inputs@{ self, nixpkgs, + + + + + nix2container , + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14, + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4, + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527, + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7, + }: let + supportedSystems = [ "x86_64-linux" "aarch64-darwin" "x86_64-darwin" "aarch64-linux" ]; + + + forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f { + inherit system; + nix2containerPkgs = nix2container.packages.${system}; + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs = import nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14 { inherit system; }; + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs = import nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4 { inherit system; }; + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs = import nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527 { inherit system; }; + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs = import nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7 { inherit system; }; + + + pkgs = import nixpkgs { inherit system; }; + + + }); + in { + + devShells = forEachSupportedSystem ({ pkgs, + + + + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs, + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs, + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs, + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs, + ... }: { + devShell = pkgs.mkShell { + # The Nix packages provided in the environment + packages = [ + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs.bash + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs.coreutils-full + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs.ruby + + ]; + }; + }); + + runtimeEnvs = forEachSupportedSystem ({ pkgs, + + + + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs, nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs, nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs, nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs, ... }: { + runtime = pkgs.buildEnv { + name = "runtimeenv"; + paths = [ + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs.cacert + + ]; + }; + }); + + devEnvs = forEachSupportedSystem ({ pkgs, + + + + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs, nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs, nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs, nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs, ... }: { + development = pkgs.buildEnv { + name = "devenv"; + paths = [ + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs.bash + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs.coreutils-full + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs.ruby + + ]; + }; + }); + + + + + +ociImage_build = forEachSupportedSystem ({ pkgs, nix2containerPkgs, system , nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs, nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs, nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs, nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs, ... }: { + + + + ociImage_build_base = nix2containerPkgs.nix2container.buildImage { + name = "ttl.sh/ruby-base"; + config = { + cmd = [ ]; + entrypoint = [ ]; + env = [ + + ]; + ExposedPorts = { + + }; + }; + maxLayers = 100; + layers = [ + (nix2containerPkgs.nix2container.buildLayer { + copyToRoot = [ + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs.cacert + ]; + }) (nix2containerPkgs.nix2container.buildLayer { + copyToRoot = [ + nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs.ruby + ]; + }) (nix2containerPkgs.nix2container.buildLayer { + copyToRoot = [ + nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs.bash + ]; + }) (nix2containerPkgs.nix2container.buildLayer { + copyToRoot = [ + nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs.coreutils-full + ]; + }) + + ]; + }; + + + + + ociImage_build_base-as-dir = pkgs.runCommand "image-as-dir" { } "${inputs.self.ociImage_build.${system}.ociImage_build_base.copyTo}/bin/copy-to dir:$out"; + + }); + +ociImage_runtime = forEachSupportedSystem ({ pkgs, nix2containerPkgs, system , nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs, nixpkgs-7445ccd775d8b892fc56448d17345443a05f7fb4-pkgs, nixpkgs-4a6ce1efede1f89a857e0cc514d5d11e56621527-pkgs, nixpkgs-1ebb7d7bba2953a4223956cfb5f068b0095f84a7-pkgs, ... }: { + + + + ociImage_runtime_base = nix2containerPkgs.nix2container.buildImage { + name = "ttl.sh/ruby-base"; + config = { + cmd = [ ]; + entrypoint = [ ]; + env = [ + + ]; + ExposedPorts = { + + }; + }; + maxLayers = 100; + layers = [ + (nix2containerPkgs.nix2container.buildLayer { + copyToRoot = [ + nixpkgs-ac5c1886fd9fe49748d7ab80accc4c847481df14-pkgs.cacert + ]; + }) + + ]; + }; + + + + + ociImage_runtime_base-as-dir = pkgs.runCommand "image-as-dir" { } "${inputs.self.ociImage_runtime.${system}.ociImage_runtime_base.copyTo}/bin/copy-to dir:$out"; + + }); + + + + + }; +} diff --git a/ruby-server-example/main.rb b/ruby-server-example/main.rb new file mode 100644 index 0000000..03667e3 --- /dev/null +++ b/ruby-server-example/main.rb @@ -0,0 +1,43 @@ +require "socket" +require "json" +require "active_support/all" + +port = ENV.fetch("PORT", 9898).to_i +server = TCPServer.new port +puts "Listening on port #{port}..." + +def handle_request(request) + method, path, _ = request.split(" ") + + case [method, path] + when ["GET", "/ping"] + { code: 200, body: "Pong!" } + else + { code: 404, body: "Not Found" } + end +end + +def send_response(client, response) + status_line = case response[:code] + when 200 then "HTTP/1.1 200 OK\r\n" + when 404 then "HTTP/1.1 404 Not Found\r\n" + when 400 then "HTTP/1.1 400 Bad Request\r\n" + else "HTTP/1.1 500 Internal Server Error\r\n" + end + + headers = response[:headers] || { "Content-Type" => "text/html" } + headers_section = headers.map { |k, v| "#{k}: #{v}" }.join("\r\n") + + client.write(status_line) + client.write(headers_section + "\r\n\r\n") + client.write(response[:body]) if response[:body] +end + +loop do + Thread.start(server.accept) do |client| + request = client.readpartial(2048) + response = handle_request(request) + send_response(client, response) + client.close + end +end \ No newline at end of file