{"id":23524146,"url":"https://github.com/kimtth/jerry-web-render-was","last_synced_at":"2026-01-24T17:32:30.249Z","repository":{"id":103355281,"uuid":"99691291","full_name":"kimtth/jerry-web-render-was","owner":"kimtth","description":"🐹🌊 How web works inside client and server side. focusing on browser rendering and web application server.","archived":false,"fork":false,"pushed_at":"2025-11-27T08:16:28.000Z","size":477,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-29T21:20:58.834Z","etag":null,"topics":["browser-rendering","http-client","http-server","servlet-container","tomcat"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kimtth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-08-08T12:40:24.000Z","updated_at":"2025-11-27T08:17:43.000Z","dependencies_parsed_at":"2025-04-19T22:53:55.699Z","dependency_job_id":"540d7a57-fd0f-4431-9f36-26fc45cffe56","html_url":"https://github.com/kimtth/jerry-web-render-was","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kimtth/jerry-web-render-was","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimtth%2Fjerry-web-render-was","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimtth%2Fjerry-web-render-was/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimtth%2Fjerry-web-render-was/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimtth%2Fjerry-web-render-was/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kimtth","download_url":"https://codeload.github.com/kimtth/jerry-web-render-was/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kimtth%2Fjerry-web-render-was/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28732606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser-rendering","http-client","http-server","servlet-container","tomcat"],"created_at":"2024-12-25T18:14:42.746Z","updated_at":"2026-01-24T17:32:30.242Z","avatar_url":"https://github.com/kimtth.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Browser rendering \u0026 Web Application Server\n\nHow the web works inside the client and server-side. This project focuses on browser rendering and web server implementation. 🗂️ Built with in Java, Rust, and Python.\n\n## Contents\n\n- [Project Structure](#project-structure)\n- [Web Browser Rendering Engine](#web-browser-rendering-engine)\n  - [Rendering Pipeline](#rendering-pipeline)\n  - [Implementations](#implementations)\n  - [Running the Renderer](#running-the-renderer)\n  - [Sample Output](#sample-output)  - [Rendering Comparison (Python vs Rust)](#rendering-comparison-python-vs-rust)  - [Bug Fixes (Java Implementation)](#bug-fixes-java-implementation)\n- [Simple Container (Web Application Server)](#simple-container-web-application-server)\n  - [Architecture](#architecture)\n  - [Container Hierarchy](#container-hierarchy-tomcat-like)\n  - [Features](#features)\n  - [Running the Server](#running-the-server)\n  - [API Endpoints](#api-endpoints)\n  - [Servlet Implementation](#servlet-implementation)\n- [NIO HTTP Client/Server](#nio-http-clientserver)\n- [HTTP Protocol Notes](#http-protocol-notes)\n- [Development](#development)\n- [References](#references)\n\n---\n\nThis project consists of three main components:\n1. **A toy web browser rendering engine** — Implemented in Java, Rust, and Python\n2. **A simple web application server (servlet container)** — Implemented in Java\n3. **NIO HTTP Client/Server** — Minimal Java NIO example\n\n![web_render](https://user-images.githubusercontent.com/13846660/28877364-1db9bc8e-77d7-11e7-8370-f15f47072f0c.PNG)\n\n*Image from [limpet.net/mbrubeck](https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html)*\n\nThe toy web browser engine is influenced by [limpet.net/mbrubeck's Rust works](https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html).\n\n**Rendered output of test data with** `perf-rainbow.html` and `perf-rainbow.css`.\n\n![web_render](output/output_python_perf.png)\n\n## Web Browser Rendering Engine\n\nThe rendering engine parses HTML and CSS, builds a style tree, calculates layout, and paints pixels to an image.\n\n### Rendering Pipeline\n\n1. **HTML Parsing** → DOM Tree\n2. **CSS Parsing** → Stylesheet\n3. **Style Tree** → DOM + CSS Rules applied\n4. **Layout Tree** → Box model calculations\n5. **Painting** → Pixel output\n\n### Implementations\n\n| Language | Directory | Description |\n|----------|-----------|-------------|\n| Java | `render/` | Original implementation |\n| Rust | `rust/` | Reference implementation |\n| Python | `python/` | New implementation |\n\n### Running the Renderer\n\n#### Using Test Scripts\n\n**Windows:**\n```batch\nrender_test.bat python          # Run Python renderer\nrender_test.bat rust            # Run Rust renderer\nrender_test.bat all             # Run both and compare\n\n# With custom files\nrender_test.bat python --html custom.html --css custom.css\n```\n\n**Linux/Mac:**\n```bash\n./render_test.sh python         # Run Python renderer\n./render_test.sh rust           # Run Rust renderer\n./render_test.sh all            # Run both and compare\n\n# With custom files\n./render_test.sh python --html custom.html --css custom.css\n```\n\n#### Running Manually\n\n**Python:**\n```bash\ncd org.web.labs.inside.jerry/src/jerry/python\npip install Pillow  # Required for image output\npython main.py -H ../test/test.html -c ../test/test.css -o output.png -v\n```\n\n**Rust:**\n```bash\ncd org.web.labs.inside.jerry/src/jerry/rust\ncargo run -- -h ../test/test.html -c ../test/test.css -o output.png\n```\n\n**Java:**\n```bash\n# Compile and run RenderMain.java\n# Update file paths in RenderMain.java first\n```\n\n---\n\n## Simple Container (Web Application Server)\n\nA lightweight servlet container implementation that combines an HTTP server with a class loader.\n\n### Architecture\n\n```mermaid\ngraph TD\n    subgraph SimpleContainer\n        subgraph HTTP_Layer[HTTP Server \u0026 Handling]\n            SL(Socket Listener)\n            TP(Thread Pool\u003cbr/\u003ecached executor)\n            RH(Request Handler\u003cbr/\u003eHealth \u0026 Servlets)\n            \n            SL --\u003e TP(Accepts \u0026 Delegates Connection)\n            TP --\u003e RH(Executes Request)\n        end\n        \n        subgraph Servlet_Management[Servlet Management]\n            CL(ClassLoader\u003cbr/\u003eURLClassLoader)\n            SC(Servlet Cache\u003cbr/\u003eSingleton Inst.)\n            CHM(Concurrent Map\u003cbr/\u003eThread-Safe Storage)\n            \n            CL --\u003e SC(Loads Class into Cache)\n            SC --\u003e CHM(Stores Servlet Instances)\n        end\n        \n        subgraph HTTP_Data_Model[HTTP Data Components]\n            REQ(HttpRequest)\n            RES(HttpResponse)\n            HDR(HttpHeader \u0026 Status)\n        end\n    end\n    \n    subgraph Deployment_Structure[webapps/ Directory]\n        WEBINF[WEB-INF/]\n        CLASSES[classes/\u003cbr/\u003e.class files]\n        LIB[lib/\u003cbr/\u003e.jar dependencies]\n        \n        WEBINF --\u003e CLASSES\n        WEBINF --\u003e LIB\n    end\n    \n    RH --\u003e CL(Needs Servlet for Request)\n    CL --\u003e Deployment_Structure(Loads Class/Resource)\n    \n    style SL fill:#ccf,stroke:#333\n    style RH fill:#bbf,stroke:#333\n    style CL fill:#fcf,stroke:#333\n```\n\n### Container Hierarchy (Tomcat)\n\n1. **Engine** - Represents the entire Catalina servlet engine (e.g., Catalina)\n2. **Host** - Represents a virtual host with multiple contexts (e.g., localhost)\n3. **Context** - Represents a web application with one or more wrappers\n4. **Wrapper** - Represents an individual servlet\n\nEach container has Realm (Authentication), Valve (Request/Response processing), and Logger.\n\n### Features\n\n- **Servlet Registration \u0026 Caching** - Thread-safe servlet management\n- **Configurable Context Path** - Customize webapp location\n- **Graceful Shutdown** - Proper resource cleanup\n- **Health Check Endpoint** - `/health` returns server status\n- **Servlet List Endpoint** - `/servlets` returns registered servlets\n- **Query String Parsing** - Full URL parameter support\n- **Thread Pool** - Configurable concurrent request handling\n\n### Running the Server\n\n```bash\n# Default (port 8080)\njava org.web.labs.inside.jerry.was.SimpleContainer\n\n# Custom port and context\njava org.web.labs.inside.jerry.was.SimpleContainer -p 9090 -c /path/to/webapps\n\n# Show help\njava org.web.labs.inside.jerry.was.SimpleContainer --help\n```\n\n### Command Line Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `-p, --port` | Server port | 8080 |\n| `-c, --context` | Context path | ./webapps |\n| `-h, --help` | Show help | - |\n\n### API Endpoints\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/servlet/\u003cname\u003e` | GET | Execute a servlet |\n| `/health` | GET | Health check (JSON) |\n| `/servlets` | GET | List registered servlets (JSON) |\n| `/*` | GET | Serve static files |\n\n### Example\n\nRequest: `http://localhost:8080/servlet/ToyServlet`\n\n![toyserve](https://user-images.githubusercontent.com/13846660/29072151-8aa1bee2-7c81-11e7-82c0-b7c9043e1f67.png)\n\n### Servlet Implementation\n\nCreate a servlet by implementing the `IToy` interface:\n\n```java\npackage org.web.labs.inside.jerry.was.toyservlet;\n\npublic class MyServlet implements IToy {\n    private String name = \"MyServlet\";\n    \n    public void setName(String name) { this.name = name; }\n    public String getName() { return name; }\n    \n    @Override\n    public String doService() {\n        return \"\u003chtml\u003e\u003ch1\u003eHello from \" + name + \"\u003c/h1\u003e\u003c/html\u003e\";\n    }\n}\n```\n\n### Directory Structure\n\n```\nwebapps/\n└── WEB-INF/\n    ├── classes/        # Compiled servlet classes\n    └── lib/            # JAR dependencies\n```\n\n---\n\n## NIO HTTP Client/Server\n\nThe project includes a non-blocking I/O (NIO) implementation for HTTP client and server operations.\n\n### Location\n\n```\norg.web.labs.inside.jerry/src/jerry/nio/\n├── NIOHttpClient.java  # Non-blocking HTTP client\n└── NIOHttpServer.java  # Non-blocking HTTP server\n```\n\n### Features\n\n- **Non-blocking I/O** using Java NIO Selectors and Channels\n- **State Machine** for HTTP response parsing\n- **Chunked Transfer Encoding** support\n- **Single-threaded Event Loop** architecture\n\n### Running the NIO Server\n\n```bash\n# Default port 8888\njava org.web.labs.inside.jerry.nio.NIOHttpServer\n\n# Custom port\njava org.web.labs.inside.jerry.nio.NIOHttpServer -p 9999\n```\n\n### Running the NIO Client\n\n```bash\n# Connect to localhost:8888\njava org.web.labs.inside.jerry.nio.NIOHttpClient\n\n# Connect to custom host/port\njava org.web.labs.inside.jerry.nio.NIOHttpClient -h example.com -p 80\n```\n\n### Endpoints (NIO Server)\n\n| Endpoint | Description |\n|----------|-------------|\n| `/` | Welcome page with server info |\n| `/health` | Health check (JSON) |\n| `/echo` | Echoes the request back |\n\n#### Notes on Netty (Production NIO)\n- Netty is a production-grade NIO framework offering battle‑tested event loops, backpressure, TLS, HTTP/2, and rich pipeline handlers.\n- This repo’s `nio/` server is intentionally minimal for learning: Selector loop, basic parsing, and simple handlers.\n- When building real services, prefer Netty for:\n    - Robust connection handling and performance tuning across OSes\n    - Mature HTTP codecs, chunked streaming, and WebSocket support\n    - Extensible pipeline (handlers for logging, compression, TLS, metrics)\n- Migration path: keep your request routing and business logic, and swap the low‑level selector code with Netty `ChannelInboundHandler` implementations.\n\n#### NIO vs IO vs Async — What’s the difference?\n- **Blocking I/O (IO):** Each connection handled by a dedicated thread; `read()` blocks until data arrives. Simple to reason about, but threads are expensive under high concurrency and can suffer head‑of‑line blocking.\n- **Non‑blocking I/O (NIO):** Single (or few) selector loops multiplex many connections; `read()` returns immediately if no data, and readiness is signaled by the selector. Great for thousands of sockets with lower thread counts; requires state machines for partial reads/writes.\n- **Async I/O:** OS or runtime completes operations and invokes callbacks/futures/promises. In Java, async often means NIO + completion handlers (e.g., Netty pipeline) or `CompletableFuture`; in Rust/Python it’s typically event loops (`tokio`/`asyncio`). Reduces busy‑waiting and improves latency with structured concurrency.\n- **Trade‑offs:**\n    - IO → easiest API, highest thread usage, simpler debugging.\n    - NIO → scalable with explicit readiness handling, more complex state management.\n    - Async → scalable and expressive with backpressure, requires async‑aware libraries and careful design around cancellation/timeouts.\n\n---\n\n## HTTP Protocol Notes\n\nHTTP is based on two-way transfer (request and response). Both consist of:\n- **Header** - Metadata (method, path, content-type, etc.)\n- **Body** - Content payload\n\nEach line is tokenized by CRLF (`\\r\\n`).\n\nHTTP 1.1 supports chunked transfer encoding for streaming data:\n```\n\u003cchunk-size-hex\u003e\\r\\n\n\u003cchunk-data\u003e\\r\\n\n...\n0\\r\\n\n\\r\\n\n```\n\n## Development\n\n### Prerequisites\n\n- **Java** - JDK 8 or higher\n- **Rust** - For Rust renderer (install via [rustup](https://rustup.rs/))\n- **Python 3** - For Python renderer\n- **Pillow** - Python image library (`pip install Pillow`)\n\n### Building\n\n```bash\n# Java (using javac or your IDE)\njavac -d out src/jerry/render/*.java\n\n# Rust\ncd org.web.labs.inside.jerry/src/jerry/rust\ncargo build --release\n\n# Python (no build needed)\npip install Pillow\n```\n\n## References\n\n- [Let's build a browser engine!](https://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html) - Matt Brubeck\n- [HTTP Server (Japanese)](http://qiita.com/opengl-8080/items/ca152658a0e52c786029)\n- [Understanding of Servlet Container](http://www.hanbit.co.kr/lib/examFileDown.php?hed_idx=1000)\n\n\n## License\n\nThis project is for educational purposes.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkimtth%2Fjerry-web-render-was","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkimtth%2Fjerry-web-render-was","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkimtth%2Fjerry-web-render-was/lists"}