Viết ứng dụng web hiện đại bằng ngôn ngữ C: Góc nhìn từ một sản phẩm thương mại năm 2026

Công nghệ12 tháng 10, 2026·8 phút đọc

Một lập trình viên đã xây dựng thành công sản phẩm web thương mại marketyour.games hoàn toàn bằng ngôn ngữ C và giao thức CGI, với toàn bộ ứng dụng chỉ gồm một tệp nhị phân duy nhất, một cơ sở dữ liệu SQLite và ba thư viện phụ thuộc. Bài viết phân tích lý do mô hình tưởng như lỗi thời này lại trở nên hợp lý trong bối cảnh năm 2026, khi chuỗi cung ứng phần mềm ngày càng phức tạp và dễ bị tấn công.

Viết ứng dụng web hiện đại bằng ngôn ngữ C: Góc nhìn từ một sản phẩm thương mại năm 2026

Nếu muốn làm một trang web động vào năm 1994, bạn viết một chương trình C, thả nó vào thư mục cgi-bin và để Apache fork nó theo từng yêu cầu. Ba mươi hai năm sau, một lập trình viên vừa tung ra sản phẩm web thương mại dựa trên nền tảng công nghệ gần như y hệt.

Sản phẩm marketyour.games mang đầy đủ đặc điểm của một ứng dụng web hiện đại: tài khoản người dùng, bảng điều khiển tìm kiếm dành cho nhà sáng tạo nội dung, hệ thống thư mục để sắp xếp, thanh toán qua Stripe và email giao dịch qua Postmark. Nó tuân thủ nguyên tắc tăng cường lũy tiến (progressive enhancement) và không cần bất kỳ dòng JavaScript nào.

Tất cả đều hiện đại — trừ cách nó được viết ra và cách nó được phục vụ.

BCHS: bộ công nghệ tối giản đến kinh ngạc

Tác giả gọi ngăn xếp công nghệ của mình là BCHS: OpenBSD, C, httpd và SQLite. Điểm đáng chú ý là ở đây không hề tồn tại framework, không có ngôn ngữ template, không có máy chủ cơ sở dữ liệu riêng biệt và cũng chẳng có container nào.

  • Không framework. Bạn viết một chương trình C đọc các biến môi trường CGI rồi phản hồi lại.
  • Không ngôn ngữ template. Bạn viết mã C xuất trực tiếp ra HTML.
  • Không máy chủ cơ sở dữ liệu tách biệt. Bạn mở tệp cơ sở dữ liệu thông qua API C của SQLite.
  • Không container. Bạn biên dịch một tệp nhị phân liên kết tĩnh rồi thả vào một thư mục.

Mỗi yêu cầu sẽ sinh ra một tiến trình mới. Việc triển khai phiên bản mới chỉ đơn giản là thay thế một tệp duy nhất — không cần khởi động lại máy chủ, không có thời gian chết, các yêu cầu mới tự động nhận tệp nhị phân vừa cập nhật.

Vì sao CGI không còn lỗi thời vào năm 2026?

Lý do khiến người ta từ bỏ CGI vào khoảng năm 2004 từng rất hợp lý, nhưng theo tác giả, chúng không còn đứng vững ở thời điểm hiện tại.

Chi phí fork tiến trình ngày nay không còn đắt đỏ như xưa. Các nhân hệ điều hành hiện đại đã tối ưu hóa nó rất mạnh.

Và nếu chi phí fork có trở thành vấn đề, FastCGI là một nâng cấp đủ đơn giản để giải quyết. Điểm mấu chốt là đặc tả CGI 1.1 được công bố từ năm 2004 và chưa từng thay đổi kể từ đó — nghĩa là không có API nào cần phải học thuộc lòng.

Giao diện CGI thực chất chỉ là một nhúm khái niệm HTTP cơ bản. Hiểu HTTP thì bạn đã hiểu CGI, và kiến thức đó còn đúng mãi mãi, bất kể ngôn ngữ hay nền tảng nào.

An toàn nhờ OpenBSD và bề mặt tấn công hẹp

OpenBSD nổi tiếng với các cấu hình mặc định hợp lý và những công cụ giúp bảo vệ một chương trình C, như pledge và unveil. Máy chủ httpd phục vụ nội dung từ trong một môi trường chroot mặc định, nên tệp nhị phân CGI chạy trong một góc hệ thống tệp bị cô lập hoàn toàn.

Chỉ có hai thư viện thực sự là phụ thuộc khi biên dịch: libcurl và libsodium. Cả hai đều được nhúng và biên dịch như một phần của dự án. Kết quả là một quy trình build gần như không có bộ phận chuyển động: build sạch chỉ mất vài giây, còn build lại mất chưa đến nửa giây.

Thay vì phục vụ tài nguyên tĩnh theo cách truyền thống, tác giả định tuyến toàn bộ lưu lượng từ httpd vào tệp nhị phân CGI. Mọi tài nguyên đều được biên dịch thẳng vào tệp thực thi và phục vụ từ bộ nhớ.

Lợi thế về chuỗi cung ứng phần mềm

Trong bối cảnh các tác nhân tự động (autonomous agents) ngày càng phổ biến và các kho gói phần mềm bị tấn công hằng tuần, việc có thật ít phụ thuộc mang lại cảm giác an tâm đáng kể.

Hầu hết các ngăn xếp công nghệ hiện đại đều đi kèm trình quản lý gói và cả một hệ sinh thái. Điều đó tiện lợi, nhưng đồ thị phụ thuộc sẽ phình to: một hoặc hai phụ thuộc trực tiếp có thể kéo theo hàng trăm phụ thuộc gián tiếp, mỗi thứ do một người bạn chưa từng nghe tên duy trì, với thông tin đăng nhập được bảo vệ bằng mật khẩu dùng lại từ năm 2015.

Chuỗi cung ứng của tôi chỉ gồm một trình biên dịch C và ba thư viện. Muốn xâm phạm nó thì phải xâm phạm libcurl — một dự án mà cả internet đang theo dõi, chứ không phải một gói có mười một lượt tải mỗi tuần với chủ sở hữu đã rời đi từ năm 2019.

Công cụ đơn giản vì bản thân ngăn xếp đã đơn giản

Tác giả tự nhận mình là người theo chủ nghĩa tối giản: dùng Vim cổ điển không cài plugin, nghĩa là không LSP, không tự động hoàn thành, không trình định dạng mã và không AI.

Các ngăn xếp phức tạp đòi hỏi công cụ phức tạp — chúng cần language server để len qua các tầng trừu tượng. Nhưng ngăn xếp này đơn giản đến mức một trình soạn thảo thuần túy là đủ. Toàn bộ ứng dụng chỉ là một thư mục chứa các tệp C cùng một Makefile. Mở tệp ra, đọc là biết nó làm gì.

Khi cần đến công cụ hỗ trợ, chúng luôn sẵn sàng ở gần: sanitizer, valgrind, gdb, ctags, cscope — những công cụ trưởng thành đã được tinh chỉnh suốt nhiều thập kỷ và chỉ cần cài một gói trên bất kỳ hệ thống nào biên dịch được C.

SQLite thay vì Postgres

Tác giả vốn luôn mặc định chọn Postgres cho các ứng dụng web. Đó là cơ sở dữ liệu tuyệt vời nhưng đi kèm gánh nặng vận hành: phải chăm sóc tiến trình máy chủ và thường xuyên nâng cấp các bản phát hành.

SQLite thì không có bất kỳ điều nào trong số đó — không tiến trình, không cấu hình, không phụ thuộc. Ứng dụng mở trực tiếp tệp cơ sở dữ liệu, và gánh nặng vận hành ở mức tối thiểu.

Điểm yếu cần thẳng thắn nhìn nhận

CGI là giao diện giữa máy chủ web và ứng dụng của bạn, không phải framework hay thư viện. Điều này đồng nghĩa bạn nhận được rất ít thứ có sẵn và phải tự viết các tiện ích để xử lý những việc như phân tích yêu cầu, quản lý phiên, xử lý biểu mẫu hay bảo mật đầu vào.

Tác giả đã tự viết các tiện ích này gói gọn trong một tệp header duy nhất (cgi.h), nhưng không hoàn toàn chắc chắn đó là giải pháp đúng. Các thư viện như kcgi đã tồn tại, song dùng chúng nghĩa là chấp nhận API và mô hình bảo mật của chúng. Tác giả bày tỏ mong muốn có một bộ tiện ích dùng chung mà lập trình viên có thể thả vào dự án, theo kiểu các thư viện stb.

Ý nghĩa với lập trình viên Việt Nam

Với các nhóm phát triển tại Việt Nam, đặc biệt là những nhóm nhỏ hoặc cá nhân đang vận hành sản phẩm có lưu lượng vừa phải, ngăn xếp này đáng để tham khảo vì giảm mạnh chi phí hạ tầng, đơn giản hóa quy trình triển khai và thu hẹp đáng kể bề mặt tấn công. Việc chỉ phải duy trì một tệp nhị phân duy nhất giúp giảm thiểu sai sót vận hành, còn những công cụ như SQLite và C lại nằm trong số ổn định nhất mà ngành phần mềm từng sản sinh.

Tuy vậy, cần lưu ý rằng viết web bằng C đòi hỏi kỷ luật cao về quản lý bộ nhớ và bảo mật — đây không phải con đường dành cho người mới. Giá trị lớn nhất của bài viết có lẽ nằm ở lời nhắc nhở: sự phức tạp không phải lúc nào cũng đồng nghĩa với tiến bộ.

Viết một ứng dụng web hiện đại bằng C không chỉ khả thi — marketyour.games là một sản phẩm thương mại đang chạy trên một tệp nhị phân duy nhất, sử dụng mô hình phục vụ đã được chuẩn hóa chính thức từ năm 2004. Nó có ít bộ phận chuyển động hơn bất cứ thứ gì tác giả từng triển khai trước đây, và ông khẳng định sẽ còn quay lại với ngăn xếp này.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗