Chuyên mục

Nodejs

Nodejs tutolrial

147 bài viết
path.dirname(): Thám Tử Đường Dẫn Của Gen Z Node.js
20/03/2026

path.dirname(): Thám Tử Đường Dẫn Của Gen Z Node.js

Chào các bạn Gen Z mê code, hôm nay anh Creyt sẽ cùng các em "bóc tách" một công cụ nhỏ nhưng có võ trong Node.js, đó là path.dirname(). Nghe có vẻ khô khan nhưng tin anh đi, nó thú vị hơn em tưởng nhiều! path.dirname(): Thám Tử Tìm Địa Chỉ Nhà Tưởng tượng thế này nhé: mỗi file trên máy tính của em giống như một căn nhà có địa chỉ rõ ràng. Ví dụ, C:/Users/genz_coder/projects/my_app/src/index.js. Đây là một địa chỉ đầy đủ, từ con phố lớn nhất (ổ đĩa C) cho đến số nhà (file index.js). Vậy path.dirname() làm gì? Đơn giản là nó giống như một thám tử chỉ quan tâm đến "khu phố" mà căn nhà đó tọa lạc, mà không cần biết chính xác số nhà hay tên chủ nhà là gì. Nó sẽ cắt phéng cái tên file cuối cùng đi và trả về nguyên cái đường dẫn đến thư mục chứa nó. Tóm lại: Là gì? Một hàm trong module path của Node.js. Để làm gì? Trích xuất phần thư mục (directory) từ một đường dẫn file hoặc thư mục đã cho. Nó bỏ qua tên file hoặc thư mục cuối cùng và trả về đường dẫn đến thư mục cha. Code Ví Dụ Minh Họa: "Đường Về Nhà" Để dùng path.dirname(), đầu tiên em phải "nhập khẩu" module path vào script của mình cái đã. const path = require('path'); // Case 1: Đường dẫn file thông thường const filePath1 = '/users/creyt/documents/report.pdf'; const dirName1 = path.dirname(filePath1); console.log(`Đường dẫn thư mục của '${filePath1}': ${dirName1}`); // Output: Đường dẫn thư mục của '/users/creyt/documents/report.pdf': /users/creyt/documents // Case 2: Đường dẫn thư mục (có hoặc không có dấu gạch chéo cuối) const dirPath2 = '/home/genz_app/'; const dirName2 = path.dirname(dirPath2); console.log(`Đường dẫn thư mục của '${dirPath2}': ${dirName2}`); // Output: Đường dẫn thư mục của '/home/genz_app/': /home const dirPath3 = '/home/genz_app'; // Không có dấu gạch chéo cuối const dirName3 = path.dirname(dirPath3); console.log(`Đường dẫn thư mục của '${dirPath3}': ${dirName3}`); // Output: Đường dẫn thư mục của '/home/genz_app': /home // Case 3: Đường dẫn gốc (root path) const rootPath = '/'; const dirNameRoot = path.dirname(rootPath); console.log(`Đường dẫn thư mục của '${rootPath}': ${dirNameRoot}`); // Output: Đường dẫn thư mục của '/': / const windowsRootPath = 'C:\\'; // Chú ý: trong string, '\' phải viết là '\\' để escape const dirNameWindowsRoot = path.dirname(windowsRootPath); console.log(`Đường dẫn thư mục của '${windowsRootPath}': ${dirNameWindowsRoot}`); // Output: Đường dẫn thư mục của 'C:\': C:\ // Case 4: Đường dẫn tương đối const relativePath = 'data/images/avatar.jpg'; const dirNameRelative = path.dirname(relativePath); console.log(`Đường dẫn thư mục của '${relativePath}': ${dirNameRelative}`); // Output: Đường dẫn thư mục của 'data/images/avatar.jpg': data/images const currentFileDir = __dirname; // __dirname là biến toàn cục trong Node.js, chứa đường dẫn thư mục của file hiện tại console.log(`Thư mục của file hiện tại: ${currentFileDir}`); // Output ví dụ: Thư mục của file hiện tại: /path/to/your/script Thấy chưa? Nó cực kỳ "thẳng tính", cứ cái gì nằm sau cái cuối cùng là nó "xóa sổ" hết, chỉ giữ lại "khu phố" thôi. Mẹo Vặt Của Anh Creyt (Best Practices) "Đừng Tự Làm Thám Tử Bằng Tay": Đừng bao giờ dại dột mà tự mình cắt chuỗi đường dẫn bằng split('/') hay substring()! Mỗi hệ điều hành (Windows, macOS, Linux) lại có cách dùng dấu phân cách khác nhau (\ hay /). path.dirname() sinh ra là để giải quyết vấn đề này, nó tự động nhận diện hệ điều hành và dùng dấu phân cách phù hợp. Dùng nó để code của em "chạy mượt" trên mọi nền tảng. "Bạn Thân Của path.join()": path.dirname() thường đi đôi với path.join(). Khi em đã có thư mục cha, em có thể dùng path.join() để xây dựng các đường dẫn con một cách an toàn và chuẩn chỉnh. const currentDir = path.dirname(__filename); // Lấy thư mục của file hiện tại const configFilePath = path.join(currentDir, 'config', 'app.config.json'); console.log(`Đường dẫn file config: ${configFilePath}`); // Output ví dụ: Đường dẫn file config: /path/to/your/script/config/app.config.json "Dấu Gạch Chéo Cuối Cùng Là Vô Hình": path.dirname() rất "thờ ơ" với dấu gạch chéo / (hoặc \) ở cuối đường dẫn. Nó sẽ tự động bỏ qua chúng khi xác định thư mục cha. Ví dụ, path.dirname('/home/user/') và path.dirname('/home/user') đều trả về /home. Cứ yên tâm mà dùng nhé! Ứng Dụng Thực Tế: "Ai Đã Dùng Nó?" Nhiều lắm em ơi, từ những gã khổng lồ đến các startup nhỏ đều dùng nó để "định vị" và "điều hướng" trong hệ thống file: Web Servers (như Express.js): Khi em muốn phục vụ các file tĩnh (HTML, CSS, JS, ảnh) từ một thư mục nào đó (ví dụ: thư mục public của ứng dụng), path.dirname(__filename) thường được dùng để tìm ra thư mục gốc của ứng dụng, sau đó dùng path.join() để tạo đường dẫn tuyệt đối đến thư mục public. Build Tools (như Webpack, Gulp): Các công cụ này cần biết vị trí của các file cấu hình, các module, hay nơi để xuất ra các file đã build. path.dirname() giúp chúng xác định vị trí tương đối của các tài nguyên này một cách linh hoạt. Hệ thống quản lý file/upload: Khi người dùng upload một file, em thường muốn lưu nó vào một thư mục cụ thể, chẳng hạn uploads/user_id/ten_file.jpg. path.dirname() có thể giúp em trích xuất phần uploads/user_id/ từ một đường dẫn đầy đủ, hoặc xác định thư mục gốc để tạo cấu trúc thư mục con. Thử Nghiệm Của Anh Creyt & Khi Nào Thì Nên Dùng Ngày xưa, khi anh Creyt còn là "tấm chiếu mới" như các em, anh cũng từng thử tự mình "cưa" chuỗi đường dẫn để lấy thư mục cha. Kết quả? Một mớ bòng bong không hơn không kém! Code chạy tốt trên máy Windows của anh nhưng mang sang máy Linux của thằng bạn thì "toang" ngay vì dấu / và \ khác nhau. Đó là lúc anh nhận ra path.dirname() chính là "vị cứu tinh". Khi nào nên dùng path.dirname()? Đọc file cấu hình hoặc tài nguyên: Khi file config.json của em nằm cùng thư mục với script chính (app.js), em sẽ dùng path.dirname(__filename) để lấy đường dẫn thư mục hiện tại, rồi path.join() để tạo đường dẫn đầy đủ đến config.json. Tạo thư mục tạm thời hoặc log: Em muốn tạo một thư mục logs bên cạnh file script đang chạy? path.dirname(__filename) + path.join() là lựa chọn hoàn hảo. Xử lý đường dẫn động: Khi em nhận được một đường dẫn file từ bên ngoài (ví dụ: từ API, từ người dùng) và em chỉ muốn biết nó nằm ở "khu phố" nào để xử lý tiếp (ví dụ: kiểm tra quyền truy cập vào thư mục đó). Nhớ nhé các em, path.dirname() không chỉ là một hàm, nó là một tư duy về việc xử lý đường dẫn một cách thông minh, an toàn và đa nền tảng. Hãy "kết thân" với nó để code của em "chất" hơn, "pro" hơn! Hẹn gặp lại trong bài học tiếp theo của anh Creyt! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

47 Đọc tiếp
path.basename(): Tên file đâu, chỉ điểm ngay!
20/03/2026

path.basename(): Tên file đâu, chỉ điểm ngay!

Chào các "coder nhí" tương lai của vũ trụ số! Hôm nay, anh Creyt sẽ "khui" một "bí kíp" nhỏ nhưng có võ trong Node.js, giúp các em xử lý đường dẫn file mượt mà như "lướt phím" trên TikTok. "Từ khoá" chúng ta "đào xới" hôm nay chính là path.basename(). 1. path.basename() là gì mà "hot" thế? "Thám tử" path.basename() trong Node.js, nói một cách dễ hiểu, là "chuyên gia" đi "bóc tách" đường dẫn file. Tưởng tượng một cái tên file đầy đủ như C:/Users/Creyt/Documents/bai_tap/nodejs/chu_de_hom_nay.md ấy. Dài ngoằng, lằng nhằng đúng không? path.basename() sẽ "chỉ điểm" ngay cái "tên thật" của file hoặc thư mục cuối cùng trong chuỗi đường dẫn đó, mà không cần quan tâm "họ hàng" hay "địa chỉ nhà" của nó là gì. Nó sẽ "phán" ngay: "À, ông này tên là chu_de_hom_nay.md!". Ngon lành cành đào! Mục đích "sinh ra" của nó? Đơn giản là để các em có thể dễ dàng lấy ra cái tên file "trần trụi" nhất, phục vụ cho đủ thứ mục đích: hiển thị trên giao diện, đặt tên file mới, hay đơn giản là "đọc vị" xem file đó là file gì mà không cần quan tâm nó nằm ở đâu trong "ma trận" folder. 2. Code Ví Dụ Minh Họa: "Thực chiến" ngay và luôn! Để dùng path.basename(), các em cần "triệu hồi" module path của Node.js trước nhé: const path = require('path'); // Case 1: Đường dẫn file cơ bản let fullPath1 = '/home/user/documents/report.pdf'; let fileName1 = path.basename(fullPath1); console.log(`Tên file "gốc": ${fileName1}`); // Output: report.pdf // Case 2: Đường dẫn thư mục (nó vẫn hoạt động) let folderPath = '/home/user/projects/'; let folderName = path.basename(folderPath); console.log(`Tên thư mục "gốc": ${folderName}`); // Output: projects // Case 3: Có "đuôi" mở rộng (extension) nhưng bạn muốn "cắt" nó đi let fullPath2 = '/var/www/html/index.html'; let fileNameWithoutExt = path.basename(fullPath2, '.html'); console.log(`Tên file không "đuôi": ${fileNameWithoutExt}`); // Output: index // Case 4: "Đuôi" không khớp với tham số thứ hai let fullPath3 = '/app/data/image.jpg'; let fileNameWithWrongExt = path.basename(fullPath3, '.png'); console.log(`Tên file với "đuôi" không khớp: ${fileNameWithWrongExt}`); // Output: image.jpg (vẫn giữ nguyên vì không khớp) // Case 5: Đường dẫn chỉ có tên file let simpleFile = 'my_photo.jpeg'; let baseSimpleFile = path.basename(simpleFile); console.log(`Tên file đơn giản: ${baseSimpleFile}`); // Output: my_photo.jpeg // Case 6: Đường dẫn root let rootPath = '/'; let baseRoot = path.basename(rootPath); console.log(`Tên gốc của root: ${baseRoot}`); // Output: '' (chuỗi rỗng) Các em thấy không? path.basename() "tinh ranh" lắm! Nếu không có tham số thứ hai (ext), nó sẽ trả về cả tên file lẫn đuôi. Còn nếu có ext và ext đó khớp với đuôi của file, nó sẽ "cắt phăng" cái đuôi đó đi, trả về tên file "trần trụi" nhất. 3. Mẹo (Best Practices) để "ghi nhớ" và "dùng thực tế" "Nhớ mặt đặt tên": Cứ nghĩ basename là "base name" – cái tên cơ bản nhất, cốt lõi nhất của file hoặc thư mục cuối cùng trong đường dẫn. Giống như bạn gọi tên đứa bạn thân mà không cần gọi cả họ tên dài ngoằng của nó vậy. "Đuôi" là "option": Tham số ext (đuôi mở rộng) là tùy chọn. Nếu bạn muốn tên file "không râu ria", nhớ thêm nó vào. Nhưng hãy cẩn thận, nó phải khớp chính xác với đuôi của file (bao gồm cả dấu chấm .). "Đa nền tảng" là chân ái: Module path của Node.js "khôn ngoan" lắm, nó tự động xử lý sự khác biệt giữa các hệ điều hành (Windows dùng \, Linux/macOS dùng /). Nên các em cứ yên tâm mà "code" thôi, không cần lo "đường dẫn" bị "lạc trôi" đâu. Kết hợp "combo": path.basename() thường đi đôi với path.dirname() (lấy đường dẫn thư mục cha) và path.extname() (lấy đuôi mở rộng). Ba "anh em siêu nhân" này sẽ giúp các em "xử lý" mọi "ca khó" về đường dẫn. 4. Ứng dụng "real-life" mà các "ông lớn" hay dùng path.basename() không chỉ là lý thuyết suông đâu, nó được ứng dụng "tùm lum" trong các "project" thực tế đấy: Upload File (như Google Drive, Dropbox): Khi người dùng upload một file, server cần lấy tên file gốc để lưu vào database hoặc đặt tên cho file được lưu trữ. path.basename() giúp lấy tên file "sạch" nhất. Hệ thống Quản lý Nội dung (CMS - như WordPress, Medium): Khi bạn tạo một bài viết hoặc upload hình ảnh, CMS cần hiển thị tên file một cách thân thiện hoặc tạo "slug" (URL thân thiện) từ tên file. Static Site Generators (như Next.js, Gatsby): Các công cụ này dùng basename để tự động tạo đường dẫn URL hoặc tên file đầu ra dựa trên cấu trúc thư mục của bạn. Công cụ dòng lệnh (CLI tools): Các "tool" như git hay các "script" tự động hóa thường dùng basename để xử lý các file hoặc thư mục được truyền vào làm đối số. Logging và Monitoring: Khi ghi log về các sự kiện liên quan đến file, việc chỉ ghi tên file (thay vì toàn bộ đường dẫn) giúp log ngắn gọn và dễ đọc hơn. 5. Thử nghiệm đã từng và Hướng dẫn nên dùng cho case nào Anh Creyt đã từng "đau đầu" với việc xử lý tên file khi làm các dự án lớn, đặc biệt là khi phải "đá qua đá lại" giữa các hệ điều hành. path.basename() chính là "cứu tinh" trong nhiều tình huống: Nên dùng khi: Bạn chỉ cần hiển thị tên file "đẹp đẽ" cho người dùng, không cần biết nó nằm ở đâu. Bạn muốn lưu trữ file với tên gốc (hoặc biến đổi một chút) sau khi upload. Bạn cần lọc hoặc tìm kiếm file dựa trên tên của chúng. Bạn đang xây dựng một "tool" tự động hóa mà cần lấy tên file để xử lý tiếp. Bạn muốn tạo một "slug" (chuỗi thân thiện cho URL) từ tên file. Không nên dùng khi: Bạn muốn lấy toàn bộ đường dẫn tuyệt đối của file (hãy dùng path.resolve() hoặc path.join()). Bạn muốn thay đổi thư mục chứa file (hãy dùng path.dirname() để lấy đường dẫn thư mục, sau đó kết hợp với path.join()). Bạn cần kiểm tra xem một đường dẫn có phải là thư mục hay không (hãy dùng fs.stat()). Đó, path.basename() tuy nhỏ mà có võ, giúp các em "làm chủ" thế giới đường dẫn file trong Node.js một cách "ngầu lòi"! Cứ "thực hành" nhiều vào, rồi các em sẽ thấy nó "vi diệu" thế nào. Có gì thắc mắc, cứ "comment" phía dưới nhé, anh Creyt luôn sẵn sàng "giải đáp"! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

49 Đọc tiếp
path.resolve(): GPS đường dẫn trong Node.js, không lạc lối!
20/03/2026

path.resolve(): GPS đường dẫn trong Node.js, không lạc lối!

Genz, nghe đây! Anh Creyt biết các em hay bị “lú” với mấy cái đường dẫn file trong lập trình, đúng không? Lúc thì chạy được, lúc thì báo lỗi ENOENT (Error NO ENTry) như kiểu bị ma ám. Nó giống như việc bạn bè rủ đi chơi mà chỉ nói: "Đến quán cà phê A, rẽ trái, đi thẳng là thấy." Nhưng vấn đề là: "Rẽ trái từ đâu? Đi thẳng bao xa?" Một mớ bòng bong!. Đó là lúc "thám tử" path.resolve() của Node.js xuất hiện để giải cứu cuộc chơi. Nó là một trong những "bảo bối" quan trọng nhất của module path trong Node.js, giúp bạn không bao giờ lạc lối trong mê cung thư mục nữa. path.resolve() là gì và để làm gì? Nếu ví von, thì path.resolve() chính là GPS siêu cấp của hệ thống file trong Node.js. Nó làm một nhiệm vụ duy nhất nhưng cực kỳ quan trọng: biến một chuỗi các đường dẫn (có thể là tương đối, có thể là tuyệt đối) thành một đường dẫn tuyệt đối (absolute path) hoàn chỉnh và chuẩn chỉnh nhất. Mục đích là để dù bạn có chạy script ở bất cứ đâu, nó vẫn biết chính xác file/thư mục bạn cần nằm ở vị trí nào trên ổ đĩa. Nó không thích mơ hồ, nó muốn rõ ràng, rành mạch. "Đường dẫn tuyệt đối" có nghĩa là một địa chỉ không thể nhầm lẫn, bắt đầu từ thư mục gốc của hệ thống (ví dụ: / trên Linux/macOS hoặc C:\ trên Windows). Cách path.resolve() hoạt động (Đừng tưởng bở mà sai nha!) Nghe có vẻ đơn giản, nhưng cách nó xử lý đường dẫn hơi "ngược đời" một chút, và đây là cái mà nhiều bạn hay nhầm lẫn. path.resolve() sẽ: Đọc từ PHẢI sang TRÁI: Đúng vậy, nó xử lý các đoạn đường dẫn bạn truyền vào từ cuối cùng về đầu tiên. Tìm đường dẫn TUYỆT ĐỐI đầu tiên: Khi nó gặp một đoạn đường dẫn mà bản thân nó đã là một đường dẫn tuyệt đối (ví dụ: /users/creyt hoặc C:\project), nó sẽ dùng ngay đoạn đó làm "gốc" và bỏ qua tất cả các đoạn đường dẫn phía trước nó (bên trái). Nếu không có TUYỆT ĐỐI nào: Nếu sau khi duyệt hết từ phải sang trái mà không thấy đoạn nào là đường dẫn tuyệt đối, thì nó sẽ tự động lấy thư mục làm việc hiện tại của Node.js (tức là process.cwd()) làm "gốc" để ghép vào. Dọn dẹp: Cuối cùng, nó sẽ "dọn dẹp" đường dẫn, loại bỏ các . (thư mục hiện tại) và .. (thư mục cha) để cho ra một đường dẫn sạch đẹp nhất. Code Ví Dụ Minh Họa (Sờ tận tay, day tận trán) Để dễ hình dung, anh Creyt sẽ "code" cho các em xem: const path = require('path'); // Ví dụ 1: Các đường dẫn tương đối console.log('Ví dụ 1 (Tương đối):', path.resolve('src', 'components', 'Button.js')); // Giả sử script chạy từ /home/user/my-project // Output: /home/user/my-project/src/components/Button.js // Ví dụ 2: Có lẫn đường dẫn tuyệt đối console.log('Ví dụ 2 (Lẫn tuyệt đối):', path.resolve('/var/www', 'html', 'public', '../assets', 'image.png')); // Output: /var/www/html/assets/image.png // Giải thích: Nó thấy '/var/www' là tuyệt đối, dùng nó làm gốc. Sau đó ghép 'html', 'public', '..', 'assets', 'image.png' // 'public' và '..' sẽ triệt tiêu nhau, còn lại 'assets'. // Ví dụ 3: Đường dẫn tuyệt đối ở giữa (quan trọng!) console.log('Ví dụ 3 (Tuyệt đối ở giữa):', path.resolve('users', 'creyt', '/project', 'data.json')); // Output: /project/data.json // Giải thích: Nó duyệt từ phải sang trái. Thấy '/project' là tuyệt đối, nó BỎ QUA 'users', 'creyt' và lấy '/project' làm gốc. // Ví dụ 4: Không có đối số console.log('Ví dụ 4 (Không đối số):', path.resolve()); // Output: /home/user/my-project (thư mục làm việc hiện tại) // Ví dụ 5: Kết hợp với __dirname (CỰC KỲ QUAN TRỌNG TRONG NODE.JS) // __dirname luôn trả về đường dẫn thư mục chứa file script hiện tại console.log('Ví dụ 5 (Với __dirname):', path.resolve(__dirname, '..', 'configs', 'app.config.js')); // Giả sử file script này nằm ở /home/user/my-project/src/utils/helper.js // __dirname sẽ là /home/user/my-project/src/utils // Output: /home/user/my-project/src/configs/app.config.js Mẹo (Best Practices) từ anh Creyt để không bị "lú" Luôn dùng path.resolve() cho các đường dẫn file/thư mục quan trọng: Đặc biệt là khi bạn cần đọc file config, serve static assets, hay kết nối database. Đừng bao giờ tin tưởng mù quáng vào đường dẫn tương đối, vì "tương đối" là tương đối với thư mục làm việc hiện tại, mà thư mục này có thể thay đổi tùy cách bạn chạy script. Kết hợp với __dirname hoặc __filename: Đây là bộ đôi "song kiếm hợp bích" cực mạnh. __dirname luôn cho bạn biết thư mục của file script hiện tại, còn __filename là đường dẫn file script hiện tại. Dùng chúng làm điểm neo (anchor point) cho path.resolve() để đảm bảo đường dẫn của bạn luôn chính xác, không phụ thuộc vào process.cwd(). Tưởng tượng như một bộ não logic: Khi nhìn path.resolve(A, B, C), hãy nghĩ: "Liệu C có phải tuyệt đối không? Nếu không, B có phải không? Nếu không, A có phải không? Nếu không nốt, thì lấy process.cwd() làm gốc rồi ghép A, B, C vào." Và nhớ là ../ sẽ lùi lại một cấp thư mục. Ứng dụng thực tế (Ai cũng dùng, các em cũng nên dùng!) Server Express/Koa/Hapi: Khi bạn muốn phục vụ các file tĩnh (HTML, CSS, JS, hình ảnh) từ một thư mục cụ thể, ví dụ public: // Trong Express const express = require('express'); const app = express(); const path = require('path'); app.use(express.static(path.resolve(__dirname, 'public'))); // Đảm bảo thư mục 'public' luôn được tìm thấy dù bạn chạy server từ đâu. Load file cấu hình: Các ứng dụng lớn thường có file config.json hoặc config.env. Dùng path.resolve() để đảm bảo tìm đúng file này: const path = require('path'); const configPath = path.resolve(__dirname, '..', 'configs', 'production.env'); require('dotenv').config({ path: configPath }); Các bundler (Webpack, Rollup, Vite): Chúng sử dụng path.resolve() rất nhiều để giải quyết các import modules, xác định điểm đầu vào/ra của ứng dụng. Khi nào nên dùng và không nên dùng path.resolve()? Nên dùng khi: Bạn cần một đường dẫn tuyệt đối CHẮC CHẮN: Đây là mục đích chính của nó. Nếu bạn không muốn script của mình bị "lỗi đường dẫn" khi chạy ở các môi trường khác nhau (ví dụ: chạy trên dev server, chạy trên CI/CD, chạy trên production). Đọc/ghi file, thư mục: Bất cứ khi nào tương tác với hệ thống file (FS module của Node.js), hãy dùng path.resolve() để tránh sai sót. Xây dựng đường dẫn động: Khi các thành phần đường dẫn đến từ các biến hoặc cấu hình, path.resolve() sẽ giúp bạn ghép chúng lại một cách an toàn. Không nên dùng khi: Bạn chỉ cần nối các đoạn đường dẫn lại với nhau mà không quan tâm đến tính tuyệt đối: Trong trường hợp này, path.join() sẽ là lựa chọn tốt hơn. path.join() chỉ đơn giản là nối các chuỗi lại và chuẩn hóa chúng, không cố gắng tạo ra đường dẫn tuyệt đối. const path = require('path'); console.log(path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')); // Output: /foo/bar/baz/asdf // path.resolve('/foo', 'bar', 'baz/asdf', 'quux', '..') sẽ ra: /foo/bar/baz/asdf // Nhưng nếu không có '/' ở đầu: console.log(path.join('foo', 'bar', 'baz')); // foo/bar/baz console.log(path.resolve('foo', 'bar', 'baz')); // /home/user/current_dir/foo/bar/baz Thấy sự khác biệt chưa? path.join() chỉ nối và chuẩn hóa, còn path.resolve() thì luôn cố gắng trả về đường dẫn tuyệt đối. Đó, Genz! Giờ thì các em đã có trong tay một công cụ quyền năng để không bao giờ lạc lối trong thế giới file system của Node.js nữa rồi đấy. Hãy dùng nó thông minh, và code của các em sẽ "ổn áp" hơn rất nhiều! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

48 Đọc tiếp
Path.join(): Ghép Đường Dẫn File Chuẩn Như Dân Chơi Code NodeJS
20/03/2026

Path.join(): Ghép Đường Dẫn File Chuẩn Như Dân Chơi Code NodeJS

Chào các "hacker gen Z" tương lai, hôm nay anh Creyt sẽ dắt các em đi khám phá một "công cụ" cực kỳ hữu ích trong Node.js, giúp các em "chill" hơn khi thao tác với đường dẫn file và thư mục: đó chính là path.join(). Nghe tên thì có vẻ đơn giản, nhưng nếu không biết dùng, các em dễ "toang" đấy nhé! 1. path.join() là gì và để làm gì? (Góc nhìn của Anh Creyt) Đường dẫn file (path) trong lập trình cũng giống như địa chỉ nhà của chúng ta vậy. Có lúc thì đường thẳng tắp, có lúc lại ngoằn ngoèo, lúc thì ở Hà Nội, lúc lại ở Sài Gòn. Mà khổ nỗi, cái anh Windows thì thích dùng \ làm dấu phân cách, còn macOS/Linux thì lại mê /. Nếu các em cứ "tay bo" ghép chuỗi để tạo đường dẫn, kiểu folder + '/' + file, thì đảm bảo code chạy ngon lành trên máy mình, đến khi "deploy" lên server Linux là "đứt gánh giữa đường" ngay! path.join() ra đời như một "ông thợ xây đường" chuyên nghiệp. Nhiệm vụ của ổng là ghép các mảnh đường (các phần của đường dẫn như tên thư mục, tên file) lại với nhau thành một con đường hoàn chỉnh, "chuẩn chỉ" theo hệ điều hành mà ứng dụng đang chạy. Nghĩa là, các em cứ đưa cho ổng từng mảnh, ổng sẽ tự động dùng \ hay / cho đúng, và còn dọn dẹp mấy cái dấu / hay \ thừa thãi nữa chứ. "Out trình" ghê chưa! Tóm lại, path.join() giúp các em: Ghép các đoạn đường dẫn lại với nhau: Biến ['folder', 'subfolder', 'file.txt'] thành folder/subfolder/file.txt (trên Linux) hoặc folder\subfolder\file.txt (trên Windows). Đảm bảo tính đa nền tảng (cross-platform): Không còn lo lắng về việc dấu phân cách \ hay / làm hỏng ứng dụng khi chạy trên các hệ điều hành khác nhau. Dọn dẹp đường dẫn: Tự động loại bỏ các dấu phân cách thừa, xử lý các dấu . (thư mục hiện tại) và .. (thư mục cha) một cách thông minh. 2. Code Ví Dụ Minh Hoạ "Ngon Lành Cành Đào" Để "flex" cho các em thấy path.join() "ngon" cỡ nào, cùng xem qua vài ví dụ nhé. Đầu tiên, chúng ta cần import module path của Node.js: const path = require('path'); // 1. Ghép các đoạn đường cơ bản nhất // Giả sử bạn muốn tạo đường dẫn tới file 'config.json' trong thư mục 'settings' const configPath = path.join('settings', 'config.json'); console.log('Đường dẫn config:', configPath); // Output (Linux): settings/config.json // Output (Windows): settings\config.json // 2. Anh Join tự động dọn dẹp các dấu phân cách thừa // Dù bạn có gõ thừa dấu '/' hay '\', anh Join vẫn xử lý đẹp const messyPath = path.join('/users/', 'john.doe', '/documents/', 'report.pdf'); console.log('Đường dẫn đã dọn dẹp:', messyPath); // Output (Linux): /users/john.doe/documents/report.pdf // Output (Windows): \users\john.doe\documents\report.pdf (Lưu ý: trên Windows, nếu bắt đầu bằng /, nó hiểu là từ root của drive hiện tại) // 3. Xử lý các dấu '.' và '..' để lùi thư mục // '.' là thư mục hiện tại, '..' là thư mục cha const relativePath = path.join('data', 'temp', '..', 'logs', 'error.log'); console.log('Đường dẫn tương đối:', relativePath); // Output: data/logs/error.log (đã lùi từ 'temp' về 'data' rồi vào 'logs') // 4. Khi có một đoạn đường dẫn tuyệt đối (absolute path) ở giữa // Nếu một trong các đối số là một đường dẫn tuyệt đối, các phần trước đó sẽ bị bỏ qua. const absoluteInMiddle = path.join('/home/user', 'project', '/var/log', 'app.log'); console.log('Đường dẫn với absolute ở giữa:', absoluteInMiddle); // Output (Linux): /var/log/app.log (vì '/var/log' là absolute, nên '/home/user/project' bị bỏ qua) // Output (Windows): C:\var\log\app.log (nếu C: là drive hiện tại và '/var/log' được hiểu là từ root của C:) // 5. Kết hợp với __dirname hoặc process.cwd() // Thường dùng để xây dựng đường dẫn từ thư mục hiện tại của file script hoặc thư mục làm việc. const currentDir = __dirname; // Đường dẫn đến thư mục chứa file script này const projectRootFile = path.join(currentDir, '..', 'package.json'); console.log('Đường dẫn file package.json:', projectRootFile); // Output: /path/to/your/project/package.json 3. Mẹo Vặt (Best Practices) để ghi nhớ và dùng thực tế Luôn luôn dùng path.join(): Đừng bao giờ "tự biên tự diễn" ghép chuỗi đường dẫn bằng dấu + hay template literals. Hãy để path.join() lo việc đó cho bạn. Đây là "quy tắc vàng" để code của bạn "sống sót" trên mọi hệ điều hành. Hiểu rõ sự khác biệt với path.resolve(): path.join() chỉ đơn thuần ghép các đoạn đường lại. Còn path.resolve() thì mạnh mẽ hơn, nó sẽ phân giải một chuỗi đường dẫn thành đường dẫn tuyệt đối từ thư mục làm việc hiện tại của bạn, xử lý . và .. một cách triệt để hơn để ra một đường dẫn "sạch" và "chính xác". Khi nào cần đường dẫn tuyệt đối mà không cần quan tâm các đoạn đường đã cho, hãy nghĩ đến path.resolve(). Nhưng hôm nay, chúng ta chỉ "flex" path.join() thôi nhé! Sử dụng __dirname hoặc process.cwd(): Để đảm bảo đường dẫn luôn đúng từ một điểm gốc xác định (thư mục chứa file script hoặc thư mục làm việc), hãy kết hợp path.join() với __dirname (đường dẫn đến thư mục của file JS hiện tại) hoặc process.cwd() (current working directory - thư mục mà tiến trình Node.js được khởi chạy). 4. Góc nhìn học thuật sâu của Anh Creyt: Tại sao nó lại quan trọng "vcl" đến thế? Trong lập trình, đặc biệt là với các ứng dụng backend hay CLI tools, việc tương tác với hệ thống file là chuyện "cơm bữa". Từ việc đọc file cấu hình, ghi log, lưu trữ dữ liệu người dùng, cho đến phục vụ các file tĩnh cho web client. Mỗi thao tác đều đòi hỏi đường dẫn chính xác. Nếu đường dẫn sai, nhẹ thì lỗi "File Not Found", nặng thì có thể dẫn đến lỗ hổng bảo mật (path traversal) hoặc dữ liệu bị ghi đè lung tung. path.join() không chỉ là một hàm tiện ích, nó là một "bức tường phòng thủ" giúp code của bạn trở nên mạnh mẽ, bền vững và dễ bảo trì hơn. Nó che giấu đi sự phức tạp của việc xử lý đường dẫn đa nền tảng, cho phép các "hacker gen Z" như các em tập trung vào logic nghiệp vụ thay vì đau đầu với mấy cái dấu \ và /. 5. Ví dụ thực tế: Ứng dụng/Website đã "flex" path.join() như thế nào? "Em nó" được dùng "ngập tràn" trong các ứng dụng Node.js: Express.js (phục vụ file tĩnh): Khi bạn muốn server Express của mình phục vụ các file CSS, JS, hình ảnh từ một thư mục nào đó (ví dụ: public), bạn sẽ dùng path.join() để chỉ định đường dẫn tuyệt đối đến thư mục đó. Ví dụ: const express = require('express'); const app = express(); const path = require('path'); // Phục vụ các file tĩnh từ thư mục 'public' app.use(express.static(path.join(__dirname, 'public'))); app.listen(3000, () => console.log('Server is running on port 3000')); Đọc/Ghi file cấu hình: Các file .env, config.json hay các file data khác thường được đặt trong các thư mục cụ thể. path.join() giúp bạn tạo đường dẫn đến chúng một cách dễ dàng. const fs = require('fs'); const path = require('path'); const configFilePath = path.join(__dirname, '..', 'configs', 'app.config.json'); fs.readFile(configFilePath, 'utf8', (err, data) => { if (err) throw err; console.log('Nội dung config:', JSON.parse(data)); }); Xây dựng đường dẫn upload file: Khi người dùng upload ảnh đại diện hay tài liệu, bạn cần lưu chúng vào một thư mục cụ thể trên server. path.join() là "trợ thủ đắc lực" để tạo đường dẫn đích. 6. Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào Anh Creyt đã từng "ngây thơ" ghép chuỗi thủ công khi mới vào nghề, và kết quả là "sập nguồn" liên tục khi triển khai ứng dụng trên môi trường Linux. Sau đó, khi "ngộ" ra path.join(), mọi thứ trở nên "mượt mà" hơn rất nhiều. Nên dùng path.join() khi: Bạn cần kết hợp nhiều đoạn đường dẫn (tên thư mục, tên file) thành một đường dẫn hoàn chỉnh. Bạn muốn code của mình chạy ổn định trên cả Windows, macOS và Linux mà không cần bận tâm đến dấu phân cách. Bạn muốn xử lý các đường dẫn tương đối (có . hoặc ..) một cách thông minh. Bạn đang xây dựng đường dẫn để đọc/ghi file, phục vụ file tĩnh, hoặc bất kỳ thao tác nào liên quan đến hệ thống file mà không cần đường dẫn tuyệt đối từ gốc hệ thống (root). Khi nào nên cân nhắc dùng path.resolve() thay vì path.join()? Khi bạn cần một đường dẫn tuyệt đối cuối cùng, được phân giải từ một hoặc nhiều đoạn đường dẫn, có tính đến thư mục làm việc hiện tại (process.cwd()). path.resolve() thường được dùng khi bạn muốn đảm bảo một đường dẫn luôn là tuyệt đối, không phụ thuộc vào vị trí của file script. Ví dụ: const path = require('path'); const joinedPath = path.join('data', 'file.txt'); console.log('path.join():', joinedPath); // Output: data/file.txt const resolvedPath = path.resolve('data', 'file.txt'); console.log('path.resolve():', resolvedPath); // Output: /path/to/current/working/directory/data/file.txt (đường dẫn tuyệt đối) Thấy chưa, path.join() là một "người bạn" không thể thiếu của các "hacker" Node.js. Nắm vững nó, các em sẽ "flex" được kỹ năng quản lý đường dẫn "out trình" hơn rất nhiều. Cứ thực hành đi, rồi các em sẽ thấy nó "ngon" đến mức nào! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

47 Đọc tiếp
https.request(): Mở Cổng Liên Lạc An Toàn Cho Backend Node.js
20/03/2026

https.request(): Mở Cổng Liên Lạc An Toàn Cho Backend Node.js

Chào các "dev-ninja" tương lai của anh Creyt! Hôm nay, chúng ta sẽ "hack" một khái niệm nghe có vẻ khô khan nhưng lại là "xương sống" của mọi ứng dụng hiện đại: https.request() trong Node.js. Cứ hình dung thế này, server Node.js của em như một "đại sứ quán" của riêng em vậy. Đôi khi, đại sứ quán này cần "gửi công hàm mật" (request) đến một đại sứ quán khác (server khác) để "xin thông tin mật" (dữ liệu API) hoặc "truyền đạt chỉ thị" (gửi dữ liệu). Và https.request() chính là cái "công hàm mật" siêu an toàn, được mã hóa để không ai "nghe lén" được. 1. https.request() là gì và để làm gì? Đơn giản mà nói, https.request() là một hàm "native" (có sẵn) trong Node.js, nằm trong module https, giúp em gửi các yêu cầu HTTP (như GET, POST, PUT, DELETE) đến các server khác qua giao thức HTTPS. "HTTPS" ở đây giống như một "bộ giáp chống đạn" cho dữ liệu của em vậy. Thay vì gửi một lá thư tay mà ai cũng có thể đọc trộm (HTTP), em gửi một lá thư được niêm phong, mã hóa cẩn thận, đảm bảo chỉ người nhận mới đọc được và nội dung không bị sửa đổi trên đường đi. Mục đích chính của nó ư? Giao tiếp! Server của em cần lấy dữ liệu từ một API bên ngoài (ví dụ: lấy tỷ giá hối đoái, thông tin thời tiết, dữ liệu user từ một dịch vụ khác), hoặc gửi dữ liệu đến một dịch vụ khác (ví dụ: gửi thông báo đến dịch vụ email, cập nhật trạng thái đơn hàng). https.request() chính là "cánh cửa" để thực hiện những cuộc "đàm phán" này một cách bảo mật và tin cậy. 2. Code Ví Dụ Minh Hoạ: "Gửi Công Hàm Mật" An Toàn Đây là cách em có thể sử dụng https.request() để gửi một yêu cầu GET đơn giản đến một API nào đó. Ví dụ, anh Creyt sẽ "xin" thông tin ngẫu nhiên từ JSONPlaceholder: const https = require('https'); const options = { hostname: 'jsonplaceholder.typicode.com', port: 443, // Cổng mặc định cho HTTPS path: '/posts/1', // Đường dẫn cụ thể đến tài nguyên method: 'GET', // Phương thức HTTP headers: { 'User-Agent': 'Node.js Creyt-App/1.0', // Một header thân thiện để API nhận diện 'Accept': 'application/json' // Báo cho server biết mình muốn nhận JSON } }; console.log('Đại sứ quán của em đang gửi công hàm mật...'); const req = https.request(options, (res) => { console.log(` Nhận được phản hồi từ server!`); console.log(`Trạng thái: ${res.statusCode}`); console.log(`Headers: ${JSON.stringify(res.headers, null, 2)}`); let data = ''; // Khi có dữ liệu về, 'data' sẽ được thêm vào res.on('data', (chunk) => { data += chunk; }); // Khi nhận đủ dữ liệu, 'end' sẽ được gọi res.on('end', () => { try { const jsonData = JSON.parse(data); console.log('Dữ liệu nhận được:'); console.log(jsonData); } catch (e) { console.error('Lỗi khi parse JSON:', e.message); console.log('Dữ liệu thô:', data); } }); }); // Xử lý lỗi nếu có vấn đề khi gửi yêu cầu (ví dụ: không kết nối được server) req.on('error', (e) => { console.error(` Ôi không! Công hàm bị chặn trên đường đi: ${e.message}`); }); // Rất quan trọng: Kết thúc yêu cầu. // Đối với GET, thường không có body nên chỉ cần .end() ngay. // Đối với POST/PUT, cần .write() dữ liệu trước khi .end(). req.end(); Giải thích nhanh: options: Đây là "phần đầu" của công hàm, bao gồm địa chỉ người nhận (hostname, port), nội dung yêu cầu (path, method) và các "thông tin bổ sung" (headers). https.request(options, callback): Hàm này sẽ bắt đầu gửi yêu cầu. Khi server phản hồi, callback sẽ được gọi với đối tượng res (response) chứa thông tin phản hồi. res.on('data', ...): Dữ liệu từ server thường về từng mảnh nhỏ (chunk). Em phải "gom" chúng lại. res.on('end', ...): Khi tất cả dữ liệu đã về, em có thể xử lý nó (thường là JSON.parse nếu là API). req.on('error', ...): Đừng bao giờ quên "phương án dự phòng"! Nếu có lỗi mạng hoặc server không phản hồi, error sẽ được kích hoạt. req.end(): Bắt buộc phải gọi! Đây là lúc em "đóng gói" công hàm và gửi đi. Nếu không có nó, yêu cầu sẽ không bao giờ được gửi. 3. Mẹo (Best Practices) từ "Đại Ca" Creyt Luôn xử lý lỗi (Error Handling): Như em thấy trong ví dụ, req.on('error', ...) là cực kỳ quan trọng. Đừng bao giờ tin tưởng rằng mọi thứ sẽ luôn "suôn sẻ". Mạng có thể đứt, server có thể sập, API có thể trả về lỗi. Hãy chuẩn bị cho mọi tình huống xấu nhất. Quản lý data (Stream Data): Khi nhận dữ liệu từ res.on('data'), hãy nhớ rằng nó là một stream. Tức là dữ liệu về từng chút một. Em cần "ghép" chúng lại thành một chuỗi hoàn chỉnh trước khi parse JSON. Timeout: Đôi khi server phản hồi quá chậm hoặc không phản hồi. Hãy đặt một timeout trong options để yêu cầu tự động hủy sau một khoảng thời gian nhất định, tránh việc ứng dụng của em "treo" vô thời hạn. // Thêm vào options: timeout: 5000, // 5 giây Và xử lý sự kiện timeout: req.on('timeout', () => { req.destroy(); // Hủy yêu cầu console.error('Yêu cầu bị timeout!'); }); Sử dụng thư viện "xịn sò" hơn: https.request() là "công cụ thô sơ" nhưng mạnh mẽ. Trong các dự án thực tế, anh Creyt thường khuyên dùng các thư viện như axios hoặc node-fetch. Chúng "đóng gói" tất cả những logic xử lý stream, error handling, timeout... này lại cho em, giúp code "sạch" và dễ đọc hơn rất nhiều. Coi như https.request() là "nền móng" để hiểu cách mọi thứ hoạt động, còn thư viện là "ngôi nhà cao tầng" được xây dựng trên nền móng đó. 4. Ứng dụng thực tế: "Đại sứ quán" của em làm gì? Microservices: Các công ty lớn thường chia ứng dụng thành nhiều "dịch vụ nhỏ" độc lập (microservices). Mỗi dịch vụ có thể cần gọi đến dịch vụ khác để lấy hoặc gửi dữ liệu. https.request() (hoặc các thư viện dựa trên nó) là "dây thần kinh" kết nối chúng. Tích hợp API bên thứ ba: Website của em muốn hiển thị giá cổ phiếu, thông tin thời tiết, tin tức mới nhất, hoặc gửi email/SMS qua các dịch vụ như SendGrid, Twilio. Tất cả đều cần gửi yêu cầu HTTPS. Webhooks: Khi có một sự kiện xảy ra ở một hệ thống khác (ví dụ: có người đăng ký tài khoản mới trên Stripe), Stripe sẽ gửi một yêu cầu HTTPS (webhook) đến server của em để thông báo. Ngược lại, server của em cũng có thể gửi webhook đến các dịch vụ khác. 5. Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào? Anh Creyt đã từng "đau đầu" với https.request() khi phải xử lý từng chunk dữ liệu, từng loại lỗi một trong những ngày đầu. Nó dạy anh rất nhiều về cách HTTP hoạt động ở mức độ thấp. Tuy nhiên, trong các dự án hiện đại, anh thường chỉ dùng https.request() khi: Cần kiểm soát tuyệt đối: Em muốn tự tay "nặn" từng byte của request, hoặc cần xử lý các trường hợp rất đặc biệt mà thư viện không hỗ trợ. Dự án cực kỳ nhỏ gọn: Không muốn thêm dependency (thư viện) nào vào dự án để giữ cho kích thước bundle nhỏ nhất. Học tập và nghiên cứu: Để hiểu sâu về cách Node.js giao tiếp với thế giới bên ngoài, không gì bằng tự tay viết từ https.request(). Khi nào nên dùng thư viện (như Axios, Node-Fetch)? Đa số các trường hợp thực tế: Đặc biệt là khi em làm việc với nhiều API, cần xử lý nhiều loại request (GET, POST, PUT, DELETE), cần quản lý headers, body, error handling một cách dễ dàng và hiệu quả hơn. Thư viện sẽ giúp em tiết kiệm rất nhiều thời gian và công sức, giảm thiểu lỗi. Dự án cần nhanh chóng, dễ bảo trì: Code dùng thư viện thường ngắn gọn, dễ đọc và dễ debug hơn. Nhớ nhé các "dev-ninja", https.request() là "công cụ cơ bản" nhưng cực kỳ quan trọng. Nắm vững nó, em sẽ hiểu được "trái tim" của mọi giao tiếp mạng trong Node.js. Nhưng đừng ngại "nâng cấp" lên các "công cụ tự động" (thư viện) khi cần! Đó mới là cách làm việc của một "dev-ninja" thông thái! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

42 Đọc tiếp
https.get(): Bí kíp Node.js "gọi hàng" từ Internet (An toàn & Chất)
20/03/2026

https.get(): Bí kíp Node.js "gọi hàng" từ Internet (An toàn & Chất)

Alo alo, Gen Z! Creyt đây, và hôm nay chúng ta sẽ cùng nhau khám phá một "công cụ" cực kỳ quyền năng trong bộ đồ nghề của một lập trình viên Node.js: https.get()! Nghe có vẻ khô khan nhưng tin anh đi, nó chính là chiếc chìa khóa để apps của mấy đứa "nói chuyện" được với thế giới bên ngoài đấy. 1. https.get() là gì mà nghe ngầu vậy anh Creyt? Tưởng tượng thế này: App Node.js của mấy đứa đang ở nhà, cần lấy thông tin từ một "người hàng xóm" nào đó trên internet (ví dụ: dữ liệu thời tiết từ một API, hay một bài đăng trên blog). Thay vì tự mình chạy sang gõ cửa, mấy đứa sẽ cử một "người đưa thư đặc biệt" đi. https.get() chính là anh chàng người đưa thư đó! Cụ thể hơn, https.get() trong Node.js là một phương thức được cung cấp bởi module https (đừng nhầm với http nhé, s ở đây là Secure - bảo mật đó!). Nhiệm vụ của nó là gửi một yêu cầu GET đến một địa chỉ web (URL) an toàn (có chứng chỉ SSL/TLS, tức là https:// chứ không phải http:// "trần truồng" đâu nha). "GET" ở đây có nghĩa là "Lấy về", giống như mấy đứa chỉ muốn xem thông tin thôi chứ không gửi gì đi cả. Để làm gì? Đơn giản là để: Lấy dữ liệu từ API: Đây là ứng dụng phổ biến nhất. Ví dụ, lấy danh sách sản phẩm từ API của Shopee, hay thông tin người dùng từ API của Facebook (nếu có quyền). Đọc nội dung trang web: Mặc dù không phải là công cụ tối ưu cho web scraping phức tạp, nhưng nó là nền tảng để lấy về mã HTML của một trang web. Kiểm tra trạng thái dịch vụ: Xem một dịch vụ online nào đó có đang hoạt động hay không. Nói chung, bất cứ khi nào app Node.js của mấy đứa cần "hỏi thăm" và "nhận thông tin" từ một nguồn bên ngoài qua đường internet một cách bảo mật, https.get() chính là lựa chọn cơ bản và tin cậy. 2. Code Ví Dụ: "Hàng xóm" ơi, cho tớ xin ít dữ liệu! Giờ thì mình cùng xem anh chàng người đưa thư này hoạt động như thế nào qua một ví dụ cụ thể. Chúng ta sẽ "nhờ" https.get() lấy về một vài bài viết mẫu từ một API công cộng (JSONPlaceholder) nhé. Đây là một sân chơi tuyệt vời để mấy đứa thử nghiệm API mà không sợ làm hỏng gì của ai đâu. const https = require('https'); const url = 'https://jsonplaceholder.typicode.com/posts/1'; // Lấy bài viết số 1 console.log('Đang cử người đưa thư đi lấy dữ liệu...'); https.get(url, (res) => { let data = ''; // Khi có dữ liệu về, 'người đưa thư' sẽ đưa từng 'mẩu' nhỏ res.on('data', (chunk) => { data += chunk; }); // Khi 'người đưa thư' đã mang về hết tất cả 'mẩu' dữ liệu res.on('end', () => { // Kiểm tra xem 'người hàng xóm' có trả lời OK không (mã 200) if (res.statusCode === 200) { try { const post = JSON.parse(data); // Thử mở 'gói hàng' (chuỗi JSON) ra xem bên trong có gì console.log('Dữ liệu đã về tới:', post); console.log('Tiêu đề bài viết:', post.title); } catch (e) { console.error('Người đưa thư mang về gói hàng bị lỗi, không đọc được JSON:', e.message); } } else { console.error(`Người đưa thư báo: "Người hàng xóm không OK!" - Mã trạng thái: ${res.statusCode}`); } }); }).on('error', (err) => { // Ối! Người đưa thư gặp sự cố trên đường đi (mất mạng, sai địa chỉ...) console.error('Người đưa thư gặp sự cố trên đường:', err.message); }); Giải thích "sương sương" từng dòng code: const https = require('https');: Kêu gọi anh chàng người đưa thư "https" vào làm việc. https.get(url, (res) => { ... });: Cử người đưa thư đi đến url và dặn dò "khi nào có hồi âm thì về báo cáo lại qua hàm res này nhé". res chính là "phản hồi" từ người hàng xóm. res.on('data', (chunk) => { ... });: Dữ liệu về thường không phải một cục mà là từng "mẩu" nhỏ (chunk). Mình phải gom từng mẩu lại vào biến data. res.on('end', () => { ... });: Khi tất cả các mẩu đã về hết, đây là lúc mình có "gói hàng" hoàn chỉnh. res.statusCode === 200: Kiểm tra xem "người hàng xóm" có trả lời "OK, tôi gửi rồi đây!" (mã 200) hay "Xin lỗi, không có gì!" (mã 404), hay "Tôi đang bận!" (mã 500) không. JSON.parse(data);: Nếu dữ liệu là JSON, thì phải "mở gói hàng" ra để dùng được. Nhớ try...catch vì lỡ gói hàng không phải JSON chuẩn thì sao? .on('error', (err) => { ... });: Đây là phần cực kỳ quan trọng! Lỡ người đưa thư gặp sự cố trên đường (mất mạng, địa chỉ không tồn tại) thì sao? Phải có cách để xử lý chứ! 3. Mẹo "sống còn" khi dùng https.get() (Best Practices) của anh Creyt Dùng https.get() cũng giống như lái xe vậy, biết lái thôi chưa đủ, phải biết mẹo để lái an toàn và hiệu quả: LUÔN LUÔN xử lý lỗi (.on('error')): Đây là điều tiên quyết! Mạng có thể rớt, server có thể sập, URL có thể sai. Nếu mấy đứa không xử lý lỗi, app của mấy đứa sẽ "crash" ngay lập tức. Giống như không đeo dây an toàn khi lái xe vậy. Kiểm tra res.statusCode: Đừng bao giờ tin tưởng mù quáng rằng dữ liệu về là "ngon". Mã 200-299 là thành công. 4xx là lỗi từ phía client (mấy đứa gửi sai gì đó), 5xx là lỗi từ phía server (người hàng xóm có vấn đề). Cẩn thận khi JSON.parse(): Dữ liệu từ ngoài internet không phải lúc nào cũng là JSON hợp lệ. Luôn bọc nó trong try...catch để tránh app bị sập nếu dữ liệu "lởm". Gom đủ "mẩu" dữ liệu: Nhớ dùng biến data để nối các chunk lại. Nếu không, mấy đứa chỉ có thể đọc được một phần dữ liệu thôi. Hạn chế dùng https.get() trực tiếp cho tác vụ phức tạp: Đối với các ứng dụng thực tế, mấy đứa sẽ thấy các thư viện như axios hoặc node-fetch được dùng nhiều hơn. Chúng nó là "người đưa thư phiên bản nâng cấp", có nhiều tính năng tiện lợi hơn (tự động parse JSON, xử lý lỗi tốt hơn, cấu hình request dễ dàng hơn...). https.get() là nền tảng, nhưng đôi khi cần "đồ chơi" xịn hơn. 4. Ứng dụng thực tế: Ai đang dùng https.get() (hoặc anh em của nó)? Hầu hết các ứng dụng web và di động mà mấy đứa đang dùng hàng ngày đều sử dụng cơ chế này (hoặc các thư viện xây dựng trên nó) để giao tiếp với server: Mấy app mạng xã hội (Facebook, Instagram, TikTok): Khi mấy đứa lướt feed, app sẽ dùng https.get() (hoặc tương đương) để lấy về các bài đăng, ảnh, video mới từ server. Các trang thương mại điện tử (Shopee, Lazada, Tiki): Khi mấy đứa tìm kiếm sản phẩm, xem chi tiết sản phẩm, app sẽ gửi request để lấy thông tin sản phẩm, giá cả, đánh giá. Các dịch vụ thời tiết, bản đồ: Lấy dữ liệu dự báo thời tiết, thông tin địa điểm, lộ trình từ các API chuyên biệt. Các backend Node.js: Một microservice có thể dùng https.get() để lấy dữ liệu từ một microservice khác (ví dụ: dịch vụ quản lý người dùng lấy thông tin từ dịch vụ quản lý đơn hàng). 5. Thử nghiệm và Nên dùng cho case nào? Thử nghiệm đã từng: Anh Creyt đã từng dùng https.get() trong những ngày đầu để xây dựng một con bot Telegram đơn giản. Con bot này cần lấy tỷ giá tiền tệ từ một API mỗi giờ. https.get() hoàn thành nhiệm vụ rất tốt vì yêu cầu đơn giản, chỉ cần GET dữ liệu JSON và không có quá nhiều cấu hình phức tạp. Nó nhẹ nhàng và không cần thêm thư viện nào cả. Nên dùng cho case nào? Học tập và làm quen: Đây là cách tuyệt vời để hiểu cách Node.js tương tác với internet ở cấp độ thấp nhất. Các request GET đơn giản, không cần cấu hình phức tạp: Nếu mấy đứa chỉ cần lấy về một tệp tin JSON hoặc HTML mà không cần gửi header tùy chỉnh, authentication phức tạp, hay xử lý body request, https.get() là đủ. Khi muốn tối giản dependency: Nếu dự án của mấy đứa cần nhỏ gọn nhất có thể và không muốn thêm thư viện bên ngoài, https.get() là lựa chọn mặc định. Xây dựng các thư viện HTTP riêng: Nếu mấy đứa muốn tự xây dựng một thư viện HTTP "xịn xò" hơn, https.get() (và https.request) là nền tảng cơ bản để bắt đầu. Tuy nhiên, nếu mấy đứa đang xây dựng một ứng dụng lớn, có nhiều loại request (POST, PUT, DELETE), cần quản lý header, timeout, retry logic, hay muốn tích hợp dễ dàng với Promise/async-await, thì hãy nghĩ đến việc "nâng cấp" lên axios hay node-fetch. Chúng sẽ giúp mấy đứa tiết kiệm rất nhiều thời gian và công sức đấy! Tóm lại, https.get() giống như việc mấy đứa học cách tự xây một chiếc xe đạp. Nó là nền tảng vững chắc để hiểu cơ chế hoạt động. Còn khi cần đi xa hơn, nhanh hơn, thoải mái hơn, thì có thể mấy đứa sẽ muốn mua một chiếc xe hơi (như axios chẳng hạn). Nhưng không có chiếc xe đạp nào thì làm sao hiểu được động cơ xe hơi hoạt động thế nào, đúng không? Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

41 Đọc tiếp
HTTPS.createServer(): Xây Pháo Đài An Toàn Cho Server Của Bạn
20/03/2026

HTTPS.createServer(): Xây Pháo Đài An Toàn Cho Server Của Bạn

Chào các Gen Z tương lai của thế giới lập trình! Anh là Creyt đây, và hôm nay chúng ta sẽ cùng nhau khám phá một khái niệm cực kỳ quan trọng, một thứ mà nếu không có nó, website của các em cũng như ngôi nhà không cửa vậy: https.createServer(). Nghe có vẻ khô khan nhưng tin anh đi, nó thú vị hơn các em nghĩ nhiều! https.createServer() là gì mà "hot" vậy? Thôi nào, đừng có nhìn cái tên mà hoảng. Tưởng tượng thế này nhé: Ngày xưa, khi các em gửi thư cho crush, các em viết lên một tấm bưu thiếp (postcard) đúng không? Ai cũng có thể đọc được nội dung trên đường đi. Đó chính là HTTP (Hypertext Transfer Protocol) – giao thức truyền tải dữ liệu cơ bản, nhưng không mã hóa. Dữ liệu của các em, từ mật khẩu, thông tin cá nhân, cho đến những dòng code "bí mật" trong API, cứ thế mà "trần truồng" trên mạng. Thế rồi, một ngày đẹp trời, các em muốn gửi thư tình mà không ai đọc trộm được. Các em cho lá thư vào phong bì, dán kín, rồi còn niêm phong bằng sáp, thậm chí dùng mực tàng hình. Đó chính là HTTPS (Hypertext Transfer Protocol Secure) – phiên bản anh em sinh đôi nhưng "ngầu" hơn, bảo mật hơn của HTTP. Nó sử dụng SSL/TLS để mã hóa toàn bộ dữ liệu trước khi gửi đi. Và https.createServer() trong Node.js chính là cái "bưu điện bảo mật" đó. Thay vì chỉ mở một cái cổng HTTP thông thường, nó mở một cái cổng HTTPS, nơi mọi thứ đều được mã hóa, bảo vệ nghiêm ngặt. Nhiệm vụ của nó là tạo ra một máy chủ web có khả năng lắng nghe và phản hồi các yêu cầu từ trình duyệt của người dùng một cách an toàn. Để làm gì ư? Bảo vệ dữ liệu: Mật khẩu, số thẻ tín dụng, thông tin cá nhân... tất cả đều được mã hóa. Hacker có bắt được gói tin cũng chỉ thấy một mớ bùng nhùng vô nghĩa. Tạo niềm tin: Người dùng nhìn thấy ổ khóa màu xanh lá cây trên trình duyệt là auto tin tưởng. "À, trang này uy tín, bảo mật." Tốt cho SEO: Google rất yêu thích các website dùng HTTPS và ưu tiên xếp hạng cao hơn. Muốn website của em lên top không? Dùng HTTPS đi! Tuân thủ quy định: Nhiều quy định về bảo mật dữ liệu (như GDPR, PCI DSS) yêu cầu phải sử dụng HTTPS. Để https.createServer() hoạt động, em cần có một cặp "chìa khóa và ổ khóa" đặc biệt, đó chính là chứng chỉ SSL/TLS (Secure Sockets Layer/Transport Layer Security). Gồm có: Private Key (Khóa riêng tư): Giống như chìa khóa nhà của em, phải giữ bí mật tuyệt đối. Certificate (Chứng chỉ): Giống như cái ổ khóa có tên em trên đó, ai cũng có thể thấy nhưng chỉ có chìa khóa của em mới mở được. Code Ví Dụ Minh Họa: "Xây Pháo Đài" Đơn Giản Đây là lúc chúng ta biến lý thuyết thành hành động. Để chạy được ví dụ này, em cần có một cặp chứng chỉ SSL/TLS. Đối với môi trường phát triển (dev), em có thể tự tạo chứng chỉ tự ký (self-signed certificate) cho nhanh. Bước 1: Tạo chứng chỉ tự ký (chỉ dùng cho dev) Mở Terminal/CMD và chạy lệnh sau (cần cài OpenSSL): openssl genrsa -out key.pem 2048 openssl req -new -key key.pem -out csr.pem openssl x509 -req -in csr.pem -signkey key.pem -out cert.pem Các em cứ điền thông tin lung tung cũng được vì đây là chứng chỉ tự ký mà. Sau khi chạy xong, các em sẽ có 3 file: key.pem (private key), csr.pem (certificate signing request - không cần dùng trực tiếp trong code này), và cert.pem (certificate). Bước 2: Viết code Node.js Tạo file server.js và thêm nội dung sau: const https = require('https'); // Import module HTTPS const fs = require('fs'); // Import module File System để đọc file chứng chỉ // Đọc các file chứng chỉ const options = { key: fs.readFileSync('key.pem'), // Đọc private key cert: fs.readFileSync('cert.pem') // Đọc certificate }; // Tạo server HTTPS // options: chứa key và cert // (req, res): hàm xử lý mỗi khi có request đến const server = https.createServer(options, (req, res) => { console.log(`Request nhận được từ: ${req.url}`); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Chào mừng đến với server HTTPS bảo mật của Creyt!\n'); }); // Lắng nghe trên cổng 443 (cổng mặc định cho HTTPS) const PORT = 443; server.listen(PORT, () => { console.log(`Server HTTPS đang chạy tại https://localhost:${PORT}`); console.log('Lưu ý: Vì đây là chứng chỉ tự ký, trình duyệt có thể báo lỗi bảo mật. Cứ chọn "Proceed anyway" nhé!'); }); // Xử lý lỗi nếu có server.on('error', (err) => { if (err.code === 'EACCES') { console.error(`Cổng ${PORT} yêu cầu quyền truy cập đặc biệt. Hãy thử chạy với 'sudo' (Linux/macOS) hoặc quyền Administrator (Windows)`); } else { console.error('Lỗi server:', err); } }); Giải thích nhanh: require('https'): Gọi "người gác cổng" HTTPS ra làm việc. require('fs'): Dùng để đọc các file key.pem và cert.pem. fs.readFileSync(): Đọc nội dung file chứng chỉ. Quan trọng là phải đọc đồng bộ để server có đủ thông tin trước khi khởi động. https.createServer(options, (req, res) => { ... }): Đây chính là trái tim của chúng ta! options: Một object chứa key và cert đã đọc từ file. Đây là thông tin để server "chứng minh thư" của mình. (req, res) => { ... }: Cái này quen rồi đúng không? Là hàm xử lý khi có ai đó gửi yêu cầu đến server của em. server.listen(PORT, callback): Bắt đầu lắng nghe các yêu cầu đến trên cổng PORT. Mặc định của HTTPS là 443. Để chạy: Đảm bảo các file key.pem và cert.pem nằm cùng thư mục với server.js. Mở Terminal/CMD, di chuyển đến thư mục đó. Chạy lệnh: node server.js Mở trình duyệt và truy cập https://localhost:443 (hoặc chỉ https://localhost). Trình duyệt sẽ báo lỗi bảo mật vì đây là chứng chỉ tự ký, cứ bỏ qua và tiếp tục nhé. Mẹo Vặt "Thực Chiến" Từ Creyt Luôn dùng HTTPS ở Production: Đừng bao giờ, ANH NHẮC LẠI LÀ ĐỪNG BAO GIỜ, chạy một ứng dụng web thật sự mà không có HTTPS. Khác nào mời hacker vào nhà uống trà. Quản lý chứng chỉ như vàng: File key.pem là private key, nó là chìa khóa vạn năng. Tuyệt đối không đẩy lên Git, không chia sẻ lung tung. Nên dùng biến môi trường (environment variables) hoặc các dịch vụ quản lý bí mật (secret management services) như AWS Secrets Manager, HashiCorp Vault. Tự động hóa gia hạn chứng chỉ: Chứng chỉ SSL/TLS có thời hạn (thường là 90 ngày với Let's Encrypt). Đừng để quên mà nó hết hạn, website của em sẽ sập và người dùng sẽ hoảng loạn. Hãy dùng các công cụ như Certbot của Let's Encrypt để tự động gia hạn. Redirect HTTP sang HTTPS: Đảm bảo tất cả các yêu cầu HTTP đều được chuyển hướng (redirect) sang HTTPS. Người dùng có gõ http:// thì vẫn phải được đưa đến https://. // Thêm vào server.js để redirect HTTP sang HTTPS const http = require('http'); http.createServer((req, res) => { res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url }); res.end(); }).listen(80, () => { console.log('Server HTTP đang chạy và redirect sang HTTPS tại http://localhost:80'); }); Chọn Cipher Suite mạnh mẽ: Cái này hơi nâng cao, nhưng hiểu nôm na là các thuật toán mã hóa được sử dụng. Hãy cấu hình để server của em chỉ chấp nhận những thuật toán mã hóa mạnh, hiện đại. // Ví dụ cấu hình cipher suite (trong options của https.createServer) const options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem'), ciphers: [ "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_GCM_SHA256", "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-RSA-AES128-GCM-SHA256" ].join(':'), honorCipherOrder: true, minVersion: 'TLSv1.2' // Đảm bảo chỉ dùng các phiên bản TLS mới nhất }; Ứng Dụng Thực Tế: Ai cũng dùng! Hầu hết mọi website, ứng dụng mà các em dùng hàng ngày đều chạy trên HTTPS, và đằng sau đó có thể là một server Node.js sử dụng https.createServer() (hoặc một proxy server như Nginx/Apache xử lý HTTPS và chuyển tiếp sang Node.js qua HTTP). Các trang thương mại điện tử: Shopee, Lazada, Tiki, Amazon... Tưởng tượng thông tin thẻ tín dụng của em mà không mã hóa thì sao? Ngân hàng trực tuyến: Vietcombank, Techcombank... Bảo mật là tối thượng. Mạng xã hội: Facebook, Instagram, TikTok... Mật khẩu, tin nhắn riêng tư, hình ảnh... không ai muốn bị lộ. Các API backend: Nếu em xây dựng một API cho ứng dụng di động hoặc frontend của mình, đặc biệt là các API liên quan đến xác thực, thanh toán, hoặc dữ liệu nhạy cảm, thì HTTPS là bắt buộc. Thử Nghiệm và Khi Nào Nên Dùng? Thử nghiệm: Như ví dụ trên, các em hoàn toàn có thể tự tạo một server HTTPS cục bộ với chứng chỉ tự ký. Việc này giúp các em hiểu rõ cách nó hoạt động, cách trình duyệt phản ứng với các chứng chỉ khác nhau. Đây là bước đệm quan trọng trước khi triển khai thực tế. Khi nào nên dùng https.createServer()? Câu trả lời đơn giản là: GẦN NHƯ LUÔN LUÔN! Ứng dụng web công khai: Bất kỳ website nào mà người dùng truy cập, dù là blog cá nhân, portfolio hay một startup tỷ đô. API backend: Đặc biệt là API cho các ứng dụng di động, SPA (Single Page Application) nơi frontend và backend giao tiếp qua mạng. Bất kỳ dịch vụ nào xử lý dữ liệu nhạy cảm: Thông tin cá nhân, tài chính, y tế, bí mật kinh doanh... Khi muốn cải thiện SEO và uy tín: Như đã nói, Google ưu tiên HTTPS. Khi nào có thể không dùng trực tiếp (nhưng vẫn dùng HTTPS)? Đôi khi, các em sẽ không dùng https.createServer() trực tiếp trong code Node.js của mình. Thay vào đó, em sẽ chạy server Node.js của mình qua HTTP trên một cổng nội bộ (ví dụ: http://localhost:3000), và đặt một Reverse Proxy như Nginx hoặc Apache ở phía trước. Cái proxy này sẽ chịu trách nhiệm xử lý HTTPS (tức là nó sẽ dùng chứng chỉ SSL/TLS và https.createServer() của riêng nó) và chuyển tiếp các yêu cầu đã được giải mã sang server Node.js của em. Ưu điểm của cách này: Nginx/Apache rất tối ưu cho việc xử lý kết nối SSL/TLS và phục vụ file tĩnh. Dễ dàng quản lý nhiều ứng dụng trên cùng một server. Node.js của em chỉ tập trung vào logic nghiệp vụ mà không phải lo lắng về việc quản lý chứng chỉ, cipher, v.v. Dù dùng cách nào, thì nguyên tắc vàng vẫn là: Dữ liệu trên mạng phải được bảo vệ! Vậy đó, các em đã thấy sức mạnh và sự cần thiết của https.createServer() rồi chứ? Hãy biến kiến thức này thành vũ khí bí mật của mình để xây dựng những ứng dụng không chỉ mạnh mẽ mà còn an toàn và đáng tin cậy! Hẹn gặp lại trong bài học tiếp theo nhé! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

37 Đọc tiếp
http.request() trong Node.js: 'Thầy' Creyt Bật Mí Bí Kíp Liên Lạc Server
20/03/2026

http.request() trong Node.js: 'Thầy' Creyt Bật Mí Bí Kíp Liên Lạc Server

http.request() trong Node.js: 'Thầy' Creyt Bật Mí Bí Kíp Liên Lạc Server Chào các bạn Gen Z mê code, hôm nay anh Creyt sẽ cùng các em khám phá một công cụ cực kỳ quyền năng trong Node.js, đó là http.request(). Nghe có vẻ khô khan nhưng tin anh đi, nó là "chìa khóa vàng" để server của chúng ta có thể "nói chuyện" với thế giới bên ngoài đấy! 1. http.request() là gì mà ghê vậy anh Creyt? Để dễ hình dung nhé, các em cứ nghĩ thế này: Server của chúng ta (ứng dụng Node.js) giống như một "đầu bếp" tài năng trong một nhà hàng. Đầu bếp này không chỉ nấu ăn mà đôi khi còn cần nguyên liệu từ các nhà cung cấp khác (các server/API khác). http.request() chính là cái điện thoại mà đầu bếp dùng để gọi điện đặt hàng nguyên liệu từ những nhà cung cấp đó. Nói một cách hàn lâm hơn, http.request() là một phương thức cấp thấp (low-level API) trong module http của Node.js, cho phép chúng ta tạo các yêu cầu HTTP (HTTP requests) đến một server từ phía client (trong trường hợp này, client chính là ứng dụng Node.js của chúng ta). Nó cung cấp cho chúng ta toàn quyền kiểm soát từng chi tiết nhỏ nhất của yêu cầu, từ header, method, body cho đến cách xử lý response. Để làm gì? Nó sinh ra để giải quyết bài toán giao tiếp giữa các hệ thống. Cụ thể hơn, http.request() giúp chúng ta: Lấy dữ liệu từ các API bên ngoài: Ví dụ, server của em cần lấy tỷ giá vàng từ một API tài chính, hay thông tin thời tiết từ một API thời tiết. Giao tiếp giữa các microservices: Nếu hệ thống của em được chia thành nhiều dịch vụ nhỏ (microservices), http.request() là cách để chúng nói chuyện với nhau. Gửi dữ liệu lên server khác: Ví dụ, em muốn gửi thông báo đến một dịch vụ SMS, hay lưu log vào một hệ thống log tập trung. Xây dựng các client HTTP tùy chỉnh: Khi các thư viện cao cấp hơn không đáp ứng được yêu cầu đặc biệt của em. 2. Code Ví Dụ Minh Họa: Từ lý thuyết đến thực chiến Ok, lý thuyết đủ rồi, giờ mình cùng xắn tay áo vào code một ví dụ cụ thể nhé. Anh sẽ minh họa cả GET và POST. Đầu tiên, anh em mình sẽ cần một server nhỏ để test. Tạo file mock-server.js: // mock-server.js const http = require('http'); const server = http.createServer((req, res) => { console.log(`[Mock Server] Received ${req.method} request to ${req.url}`); if (req.url === '/data' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Đây là dữ liệu từ Mock Server!', timestamp: Date.now() })); } else if (req.url === '/submit' && req.method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); // convert Buffer to string }); req.on('end', () => { console.log('[Mock Server] POST Body:', body); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'success', receivedData: JSON.parse(body) })); }); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Không tìm thấy API này đâu em ơi!'); } }); server.listen(3000, () => { console.log('Mock Server đang chạy ở cổng 3000. Sẵn sàng nhận yêu cầu!'); }); Chạy server này lên bằng node mock-server.js. Bây giờ, tạo file client-request.js để thực hiện yêu cầu: // client-request.js const http = require('http'); // --- Ví dụ 1: Gửi GET request để lấy dữ liệu --- const getOptions = { hostname: 'localhost', port: 3000, path: '/data', method: 'GET' }; const getReq = http.request(getOptions, (res) => { console.log(`\n--- GET Request ---`); console.log(`Trạng thái: ${res.statusCode}`); console.log(`Headers: ${JSON.stringify(res.headers)}`); let data = ''; res.on('data', (chunk) => { data += chunk; // Thu thập từng phần dữ liệu }); res.on('end', () => { try { const parsedData = JSON.parse(data); console.log('Dữ liệu nhận được:', parsedData); } catch (e) { console.error('Lỗi phân tích JSON:', e); console.log('Dữ liệu thô:', data); } }); }); getReq.on('error', (e) => { console.error(`Lỗi GET request: ${e.message}`); }); getReq.end(); // Kết thúc yêu cầu GET (không có body) // --- Ví dụ 2: Gửi POST request kèm dữ liệu --- const postData = JSON.stringify({ name: 'Creyt', age: 25, hobbies: ['coding', 'teaching', 'coffee'] }); const postOptions = { hostname: 'localhost', port: 3000, path: '/submit', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) // Quan trọng cho POST! } }; const postReq = http.request(postOptions, (res) => { console.log(`\n--- POST Request ---`); console.log(`Trạng thái: ${res.statusCode}`); console.log(`Headers: ${JSON.stringify(res.headers)}`); let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const parsedData = JSON.parse(data); console.log('Phản hồi từ POST:', parsedData); } catch (e) { console.error('Lỗi phân tích JSON:', e); console.log('Dữ liệu thô:', data); } }); }); postReq.on('error', (e) => { console.error(`Lỗi POST request: ${e.message}`); }); // Ghi dữ liệu vào body của POST request postReq.write(postData); postReq.end(); // Kết thúc yêu cầu POST Chạy node client-request.js và xem kết quả. Em sẽ thấy server nhận được yêu cầu và trả về dữ liệu đúng như mong đợi. 3. Mẹo Vặt (Best Practices) từ 'Thầy' Creyt Anh Creyt có vài tips nhỏ để các em dùng http.request() ngon lành cành đào hơn: Xử lý lỗi là VÀNG: Mạng không ổn định, server kia sập, hay trả về lỗi 500 là chuyện cơm bữa. Luôn luôn có req.on('error', ...) để bắt các lỗi network, và kiểm tra res.statusCode để xử lý lỗi từ server. Đừng bao giờ tin tưởng tuyệt đối vào hệ thống khác, em nhé! res.on('data') và res.on('end'): Nhớ rằng dữ liệu HTTP response có thể được trả về theo từng "chunk" (từng mảnh nhỏ). Em phải dùng res.on('data') để thu thập tất cả các mảnh đó lại, rồi mới xử lý toàn bộ dữ liệu khi sự kiện res.on('end') xảy ra. req.end() là bắt buộc: Dù là GET hay POST, em luôn phải gọi req.end() để báo hiệu rằng yêu cầu đã hoàn tất và sẵn sàng gửi đi. Nếu không có nó, request sẽ treo vô thời hạn đó. https cho an toàn: Nếu server đích dùng HTTPS (có chữ s cuối http), hãy dùng require('https') thay vì require('http'). Đừng cố gắng dùng http để gọi https nhé, nó sẽ không hoạt động đâu và còn nguy hiểm nữa. Content-Length và Content-Type cho POST/PUT: Khi gửi dữ liệu trong body (như POST, PUT), luôn đặt Content-Type (ví dụ application/json) và Content-Length trong headers. Content-Length báo cho server biết kích thước của dữ liệu sẽ nhận, giúp server chuẩn bị tốt hơn. Khi nào thì dùng thư viện cao cấp hơn? Thật lòng mà nói, http.request() rất mạnh nhưng cũng khá "thủ công". Trong phần lớn các dự án thực tế, các em sẽ dùng các thư viện như axios hoặc node-fetch vì chúng đơn giản hóa việc gửi request, xử lý JSON, và bắt lỗi tốt hơn nhiều. Tuy nhiên, hiểu http.request() là nền tảng để các em hiểu các thư viện đó hoạt động như thế nào, và để debug khi cần. 4. Ứng Dụng Thực Tế: Ai đang dùng http.request()? "Vậy mấy cái app xịn sò có dùng không anh?" Có chứ em! Mặc dù thường được bọc bởi các thư viện cao cấp hơn, nhưng về bản chất, http.request() (hoặc https.request()) vẫn là trái tim của mọi giao tiếp HTTP trong Node.js: API Gateway: Một server trung gian nhận request từ client, rồi dùng http.request() để gọi đến các microservices nội bộ khác để lấy dữ liệu, sau đó tổng hợp lại và trả về cho client. Webhooks: Khi một sự kiện xảy ra (ví dụ: có đơn hàng mới trên sàn TMĐT), hệ thống sẽ dùng http.request() để gửi thông báo đến một URL (webhook) mà em đã cấu hình. Server-Side Rendering (SSR): Khi em dùng Next.js, Nuxt.js, hoặc các framework SSR khác, server của em cần fetch dữ liệu từ API backend trước khi render trang. Đó chính là lúc http.request() (hoặc các thư viện dựa trên nó) vào việc. Hệ thống tích hợp: Khi cần kết nối với các hệ thống legacy (hệ thống cũ) hoặc các API có yêu cầu đặc biệt về header, chứng thực mà các thư viện phổ biến không hỗ trợ trực tiếp. 5. Thử Nghiệm của Anh Creyt và Lời Khuyên Nên Dùng Cho Case Nào Anh Creyt từng có "kỷ niệm" với http.request() khi phải tích hợp với một hệ thống thanh toán của ngân hàng cũ rích. API của họ yêu cầu một kiểu mã hóa body rất đặc biệt và phải gửi một số header tùy chỉnh mà các thư viện thông thường không cho phép tùy biến sâu đến vậy. Lúc đó, http.request() chính là "vị cứu tinh" vì nó cho anh toàn quyền kiểm soát từng byte gửi đi. Anh phải tự tay mã hóa dữ liệu, tính toán Content-Length và đặt các header "lạ đời" đó. Vậy nên dùng http.request() khi nào? Khi em cần kiểm soát tuyệt đối: Nếu em phải làm việc với các API có yêu cầu rất cụ thể về format request, header, hoặc cần tối ưu hiệu suất đến từng milisecond (bằng cách quản lý connection pool thủ công chẳng hạn). Khi em đang xây dựng một thư viện HTTP: Nếu em muốn tạo ra một thư viện fetch hoặc axios của riêng mình (chỉ để học hỏi thôi nhé, đừng làm thật rồi mang vào production!), thì http.request() là nền tảng. Khi debug sâu: Đôi khi, các thư viện cao cấp che giấu quá nhiều chi tiết. Dùng http.request() giúp em nhìn rõ hơn luồng giao tiếp HTTP, rất hữu ích khi debug các vấn đề mạng phức tạp. Khi hệ thống của em cực kỳ nhạy cảm về tài nguyên: Mặc dù hiếm, nhưng trong một số trường hợp cực đoan, việc tránh các lớp trừu tượng của thư viện cao cấp có thể giúp tiết kiệm một chút tài nguyên. Nhưng nhớ nhé, trong hầu hết các trường hợp thông thường, hãy cứ dùng axios hay node-fetch cho nhanh và tiện. http.request() giống như con dao mổ laser vậy, mạnh mẽ nhưng cần người có kinh nghiệm để dùng đúng chỗ. Còn các thư viện kia như dao thái đa năng, làm được nhiều việc mà không cần quá tỉ mỉ. Hy vọng bài giảng hôm nay của anh Creyt đã giúp các em hiểu rõ hơn về http.request() và biết khi nào nên "triệu hồi" nó ra trận. Chúc các em code vui vẻ! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

48 Đọc tiếp
http.get() trong Node.js: Đặt Grab Data Của Bạn!
20/03/2026

http.get() trong Node.js: Đặt Grab Data Của Bạn!

Chào các "thợ code" Gen Z tương lai! Anh Creyt biết mấy đứa đang "đu" theo trend lập trình, và hôm nay, chúng ta sẽ "khui" một khái niệm siêu cơ bản nhưng quyền năng trong Node.js: http.get(). Nghe có vẻ "hack não" nhưng thực ra nó dễ như "ăn kẹo" thôi! 1. http.get() là gì mà "hot" thế? "Em ơi, cho anh xin cái menu!" – Đó chính là tinh thần của http.get(). Tưởng tượng thế này: Internet là một "siêu thị" khổng lồ, và dữ liệu là vô vàn món hàng. Đôi khi, bạn muốn "ngó nghiêng" xem có gì mới, hoặc cần "lấy" một món hàng cụ thể nào đó về dùng. Lúc này, http.get() chính là "Grab" của bạn – một "phu xe" chuyên nghiệp được Node.js cử đi để "lấy hàng" về. Nói một cách "học thuật" hơn, http.get() là một phương thức trong module http "built-in" (có sẵn) của Node.js, dùng để thực hiện các yêu cầu HTTP GET đến một server nào đó. "GET" ở đây có nghĩa là "lấy", "truy xuất" dữ liệu. Nó không dùng để gửi dữ liệu nhạy cảm hay thay đổi trạng thái server đâu nhé, chỉ để "đọc" thôi. Để làm gì? Lấy dữ liệu API: Muốn hiển thị thời tiết hiện tại ư? http.get() sẽ đi hỏi "ông thần" dự báo thời tiết (API server) về nhiệt độ, độ ẩm rồi mang về cho bạn. Đọc nội dung website: Đôi khi bạn muốn lấy nội dung HTML của một trang web để "cào dữ liệu" (web scraping) hoặc đơn giản là hiển thị nó. Tải file: Dù không phải là mục đích chính, nhưng bạn có thể dùng nó để tải các file nhỏ. 2. Code Ví Dụ Minh Hoạ: "Đầu bếp" Creyt trổ tài! Để "thực hành" ngay, anh Creyt sẽ hướng dẫn các bạn "đặt hàng" một vài "món ngon" từ một API công cộng (JSONPlaceholder – một API giả lập cho dev). Đầu tiên, bạn cần "nhập khẩu" (import) module http: const http = require('http'); Giờ thì chúng ta "triệu hồi" http.get() để "lấy hàng" nhé. Hãy thử lấy danh sách các bài viết (posts): const http = require('http'); const url = 'http://jsonplaceholder.typicode.com/posts/1'; // Lấy bài viết số 1 console.log('Anh Creyt đang gửi "Grab" đi lấy dữ liệu...'); http.get(url, (res) => { const { statusCode } = res; // Mã trạng thái HTTP (200 OK, 404 Not Found, ...) const contentType = res.headers['content-type']; // Loại nội dung (application/json, text/html, ...) let error; // Biến để lưu lỗi nếu có if (statusCode !== 200) { error = new Error(`Request Failed.\nStatus Code: ${statusCode}`); } else if (!/^application\/json/.test(contentType)) { error = new Error(`Invalid content-type.\nExpected application/json but received ${contentType}`); } if (error) { console.error(`"Grab" báo lỗi: ${error.message}`); // Tiêu thụ dữ liệu phản hồi để giải phóng bộ nhớ. res.resume(); return; } res.setEncoding('utf8'); // Đặt mã hóa cho dữ liệu nhận được let rawData = ''; // Chuỗi để lưu trữ toàn bộ dữ liệu // Khi có dữ liệu về từng "miếng" (chunk) res.on('data', (chunk) => { rawData += chunk; }); // Khi toàn bộ dữ liệu đã về đủ res.on('end', () => { try { const parsedData = JSON.parse(rawData); // Thử "bóc tem" JSON console.log('Dữ liệu đã về đủ đây Gen Z ơi:'); console.log(parsedData); } catch (e) { console.error(`Lỗi khi "bóc tem" dữ liệu JSON: ${e.message}`); } }); }).on('error', (e) => { console.error(`Lỗi kết nối mạng hoặc server không phản hồi: ${e.message}`); }); Giải thích "từng đường đi nước bước" trong code: http.get(url, (res) => { ... }): Đây là lời gọi chính. url là địa chỉ bạn muốn "lấy hàng". (res) => { ... } là một hàm callback, sẽ được thực thi khi server "trả lời" (response). res (response) là một object chứa thông tin về phản hồi từ server. statusCode, contentType: Kiểm tra mã trạng thái (200 là OK, 404 là "không tìm thấy", v.v.) và loại nội dung để đảm bảo mọi thứ "ngon lành cành đào". res.resume(): Nếu có lỗi, chúng ta gọi res.resume() để đảm bảo luồng dữ liệu vẫn tiếp tục được tiêu thụ và giải phóng tài nguyên. Nếu không, kết nối có thể bị "treo". res.setEncoding('utf8'): Đảm bảo dữ liệu nhận về được mã hóa đúng chuẩn (thường là UTF-8). res.on('data', (chunk) => { ... }): Dữ liệu từ server về không phải một cục mà "nhỏ giọt" từng "miếng" (chunk). Event data sẽ "nghe ngóng" và gom từng chunk vào biến rawData. res.on('end', () => { ... }): Khi server đã gửi hết dữ liệu, event end sẽ được kích hoạt. Lúc này, rawData đã chứa toàn bộ dữ liệu. Chúng ta dùng JSON.parse() để "bóc tem" dữ liệu JSON thành object JavaScript dễ dùng hơn. .on('error', (e) => { ... }): Đây là phần cực kỳ quan trọng để "bắt" các lỗi liên quan đến kết nối mạng hoặc server không phản hồi. "Thợ code" chuyên nghiệp không bao giờ quên xử lý lỗi! 3. Mẹo "hack" để ghi nhớ và dùng thực tế (Best Practices) Luôn luôn xử lý lỗi! Giống như việc bạn không thể bỏ qua đèn đỏ, việc xử lý lỗi (cả HTTP status code và lỗi network) là bắt buộc. Nếu không, ứng dụng của bạn sẽ "sập" không báo trước. Gom data từng "miếng" (chunk): Nhớ rằng dữ liệu về từng chút một. Đừng bao giờ nghĩ nó sẽ về nguyên cục ngay lập tức. Cứ gom lại, đến khi end thì xử lý. "Bóc tem" JSON cẩn thận: Dùng try...catch khi JSON.parse() để tránh ứng dụng "tạch" nếu dữ liệu nhận về không phải JSON hợp lệ. "Nâng cấp" công cụ: Mặc dù http.get() là "gốc rễ" nhưng trong các dự án lớn, anh Creyt thường khuyên dùng các thư viện "xịn xò" hơn như axios hoặc node-fetch. Chúng cung cấp cú pháp gọn gàng hơn, tự động xử lý JSON, có tính năng "interceptors" (chặn yêu cầu/phản hồi) và xử lý lỗi "thông minh" hơn rất nhiều. Coi như http.get() là "xe đạp" để học, còn axios là "ô tô điện" vậy! 4. Ứng dụng thực tế của "Grab Data" này Website "Tin tức tổng hợp": Lấy tin tức từ nhiều nguồn API khác nhau (VnExpress, Reuters, v.v.) để hiển thị trên một trang duy nhất. Ứng dụng "Thời tiết": Gọi API của OpenWeatherMap để hiển thị dự báo thời tiết cho vị trí của bạn. Game "Online": Lấy thông tin người chơi, bảng xếp hạng từ server backend. Microservices: Trong kiến trúc microservices, các dịch vụ nhỏ thường dùng http.get() (hoặc các thư viện tương tự) để "hỏi han" dữ liệu lẫn nhau. 5. Khi nào nên dùng http.get() "nguyên bản" và khi nào nên "lên đời"? Nên dùng http.get() "nguyên bản" khi: Học tập và nghiên cứu: Khi bạn muốn hiểu sâu "ruột gan" cách HTTP request hoạt động ở cấp độ thấp nhất, http.get() là "giáo trình" tuyệt vời. Dự án siêu nhỏ, không cần dependency: Nếu bạn muốn giữ cho dự án của mình "nhẹ tênh" không cần cài thêm thư viện nào, và yêu cầu HTTP không quá phức tạp. Tạo thư viện HTTP riêng: Nếu bạn đang xây dựng một thư viện HTTP tùy chỉnh, bạn có thể dùng http module làm nền tảng. Nên "lên đời" dùng axios hoặc node-fetch khi: Dự án thực tế (production): Hầu hết các dự án cần độ tin cậy, dễ bảo trì và nhiều tính năng hơn (như timeout, retry, request/response interceptors). Xử lý JSON thường xuyên: Các thư viện này tự động parse JSON, bạn không cần phải tự gom chunk và JSON.parse() nữa. Tương tác với nhiều API khác nhau: Chúng giúp bạn quản lý các request dễ dàng hơn, đặc biệt khi phải gửi nhiều loại request (GET, POST, PUT, DELETE) với nhiều cấu hình khác nhau. Anh Creyt hy vọng qua bài này, các bạn đã "thấm" được sức mạnh và cách dùng của http.get() trong Node.js. Nhớ nhé, "biết gốc rễ" là quan trọng, nhưng "biết khi nào nên dùng công cụ xịn" còn quan trọng hơn! Giờ thì, "triển" ngay thôi, đừng ngại "bắt tay" vào code! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

44 Đọc tiếp
HTTP Server Node.js: 'Loa Phóng Thanh' Backend Của Bạn!
20/03/2026

HTTP Server Node.js: 'Loa Phóng Thanh' Backend Của Bạn!

http.createServer(): 'Loa Phóng Thanh' Backend của GenZ Hey GenZ devlings! Anh Creyt đây, và hôm nay chúng ta sẽ cùng "vibe check" một trong những viên gạch đầu tiên, nhưng cực kỳ quyền năng trong thế giới Node.js: http.createServer(). Nghe tên thì hơi "công nghiệp" tí, nhưng thực ra nó là "main character energy" của mọi ứng dụng backend Node.js đó! Tưởng tượng thế này: Internet là một khu chợ đêm siêu to khổng lồ, nơi mọi người (trình duyệt, app của bạn) cứ 'alo' gọi nhau để xin đồ (dữ liệu, trang web). Và cái http.createServer() này, nó chính là cái loa phóng thanh mà bạn đặt ở quầy hàng của mình, luôn sẵn sàng lắng nghe mọi tiếng 'alo' từ khách hàng. Khi có ai đó 'alo' (gửi một HTTP request), cái loa của bạn sẽ "báo động", và bạn (code của bạn) sẽ biết ngay để chạy ra xem khách muốn gì, rồi đưa cho họ thứ họ cần (gửi một HTTP response). Đơn giản vậy thôi, no cap! http.createServer() là gì và để làm gì? Nói một cách kỹ thuật hơn, http.createServer() là một hàm có sẵn trong module http của Node.js. Nhiệm vụ của nó là tạo ra một đối tượng server HTTP. Đối tượng server này có khả năng lắng nghe các yêu cầu đến từ trình duyệt hoặc các client khác thông qua giao thức HTTP. Cái hay của nó là bạn truyền vào một callback function (một cái hàm sẽ được gọi mỗi khi có yêu cầu đến). Hàm này nhận hai tham số: request (tất tần tật thông tin về yêu cầu của khách) và response (cái "giỏ hàng" để bạn đựng đồ và gửi trả cho khách). Code Ví Dụ Minh Hoạ Đây là cách bạn "đặt cái loa phóng thanh" của mình lên và bắt đầu lắng nghe: // Bước 1: Gọi module 'http' - như là gọi điện cho tổng đài để xin công cụ làm server vậy const http = require('http'); // Bước 2: Tạo server của bạn // http.createServer() nhận một callback function. // Hàm này sẽ chạy MỖI KHI có một request mới tới server của bạn. const server = http.createServer((req, res) => { // 'req' (request): Chứa mọi thông tin mà client gửi lên (URL, method, headers, data...) // 'res' (response): Đối tượng để bạn xây dựng và gửi phản hồi về cho client console.log(`Có một request mới tới: ${req.url} với method ${req.method}`); // Thiết lập HTTP Header cho response // res.writeHead(statusCode, headersObject) // 200 OK: Mọi thứ ngon lành cành đào // Content-Type: 'text/plain' - báo cho trình duyệt biết đây là text thuần res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); // Gửi nội dung phản hồi về cho client res.end('Chào GenZ Dev! Đây là server Node.js của anh Creyt!'); }); // Bước 3: Đặt server lắng nghe ở một cổng cụ thể // server.listen(port, [hostname], [callback]) // Mọi traffic tới cổng 3000 trên máy của bạn sẽ được server này xử lý const PORT = 3000; server.listen(PORT, () => { console.log(`Server của anh Creyt đang chạy chill chill tại http://localhost:${PORT}/`); console.log('Mở trình duyệt và truy cập địa chỉ trên để xem kết quả nhé!'); }); Cách chạy: Lưu đoạn code trên vào một file, ví dụ app.js. Mở Terminal/Command Prompt, điều hướng đến thư mục chứa file app.js. Gõ node app.js và nhấn Enter. Mở trình duyệt và truy cập http://localhost:3000/. Bạn sẽ thấy dòng chữ "Chào GenZ Dev! Đây là server Node.js của anh Creyt!" hiện ra. Giải thích code ví dụ Trong ví dụ trên, http.createServer() nhận một hàm ẩn danh. Hàm này chính là người trực quầy của bạn. Mỗi khi có khách (request) tới, người này sẽ nhận req (đơn đặt hàng của khách) và dùng res (công cụ để chuẩn bị hàng) để phản hồi lại. Ở đây, chúng ta chỉ đơn giản là gửi về một dòng chữ "Chào GenZ Dev!..." với status 200 OK. Cuối cùng, server.listen(3000) là hành động mở cửa hàng và bảo nó "Ê, mày ra cổng 3000 mà đứng chờ khách nhé!". Đơn giản vậy đó. Mẹo (Best Practices) để ghi nhớ hoặc dùng thực tế Port là cửa ngõ: Luôn dùng một cổng (port) chưa bị ứng dụng nào khác chiếm dụng. Cổng 3000, 8000, 8080 thường được dùng cho dev. Error Handling: Khi ứng dụng lớn hơn, bạn sẽ cần xử lý lỗi cẩn thận hơn trong callback function để server không bị crash. Ví dụ: server.on('error', (err) => { console.error('Server error:', err); }); Phân luồng Logic (Routing): Khi có nhiều loại request (ví dụ: /users, /products), bạn sẽ cần dùng if/else if hoặc các router module để điều hướng request đến đúng "khu vực" xử lý. Cứ như có nhiều quầy hàng trong một siêu thị vậy. Sử dụng Framework: Đối với các dự án thực tế, hiếm khi bạn dùng http.createServer() trần trụi như vậy. Thay vào đó, chúng ta sẽ dùng các framework như Express.js, Koa.js, Hapi.js. Chúng nó giống như những bộ đồ nghề "full option", giúp bạn xây dựng server nhanh hơn, dễ bảo trì hơn rất nhiều. http.createServer() là cái động cơ, còn Express là cái xe hơi hoàn chỉnh. Ứng dụng/Website đã ứng dụng (nguyên lý) Nguyên lý của http.createServer() là nền tảng cho mọi ứng dụng web và API được xây dựng với Node.js. Các ứng dụng/website đã ứng dụng nó bao gồm: API đơn giản: Các backend cho ứng dụng di động hoặc Single Page Applications (SPA) có thể bắt đầu với http.createServer() để phục vụ dữ liệu JSON. Microservices: Trong kiến trúc microservices, mỗi service nhỏ có thể dùng một instance của http.createServer() (thường là thông qua một framework) để xử lý một tác vụ cụ thể. Static File Server: Bạn có thể dùng nó để tạo một server đơn giản phục vụ các file HTML, CSS, JS tĩnh. Chat applications (WebSockets): Mặc dù WebSockets là một giao thức khác, nhưng việc nâng cấp từ HTTP sang WebSocket thường bắt đầu từ một HTTP server được tạo bởi http.createServer(). Thử nghiệm đã từng và hướng dẫn nên dùng cho case nào Anh Creyt đã từng "sống chết" với http.createServer() hồi mới chập chững vào nghề Node.js. Hồi đó, anh còn tự viết cả một cái framework "cây nhà lá vườn" chỉ dựa trên nó để hiểu sâu cách HTTP hoạt động, cách request/response được xử lý từng chút một. Cảm giác lúc đó như kiểu mình tự lắp ráp được một chiếc xe máy vậy, cực kỳ "flex"! Khi nào nên dùng http.createServer() trực tiếp? Học và hiểu sâu: Đây là cách tốt nhất để bạn nắm vững kiến thức nền tảng về cách Node.js xử lý HTTP request. Nó giúp bạn hiểu "dưới mui xe" các framework như Express hoạt động như thế nào. Viết tool nhỏ, cực kỳ nhẹ: Nếu bạn chỉ cần một server siêu đơn giản để làm một việc gì đó cực kỳ cụ thể (ví dụ: một webhook handler, một server test nhanh), dùng http.createServer() có thể là lựa chọn tối ưu, tránh "overkill" khi kéo thêm Express vào. Tạo framework của riêng bạn (cho vui hoặc học tập): Nếu bạn muốn thử sức tự xây dựng một micro-framework, đây là điểm khởi đầu. Khi nào nên dùng Framework (Express, Koa, Hapi)? 99% các dự án thực tế: Mọi dự án lớn nhỏ, từ web app, API, đến microservices, đều nên dùng framework. Chúng cung cấp sẵn các công cụ quản lý routing, middleware, template engines, error handling... giúp bạn tiết kiệm hàng tấn thời gian và công sức, đồng thời đảm bảo code sạch sẽ, dễ bảo trì hơn. Tóm lại, http.createServer() là "bản đồ khởi đầu" cho hành trình Node.js của bạn. Nắm vững nó, bạn sẽ có một nền tảng vững chắc để "combat" với mọi framework và dự án lớn sau này. Keep calm and code on, GenZ! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

52 Đọc tiếp
fs.unlinkSync(): Xóa File Cực Gắt, Đừng Để Thằng Khác Dọn Dẹp
20/03/2026

fs.unlinkSync(): Xóa File Cực Gắt, Đừng Để Thằng Khác Dọn Dẹp

Chào các đệ tử Gen Z của anh Creyt! Hôm nay, chúng ta sẽ cùng nhau "dọn dẹp" một khái niệm nghe có vẻ đơn giản nhưng lại cực kỳ quan trọng trong thế giới Node.js: fs.unlinkSync(). Nghe cái tên đã thấy mùi "dọn nhà" rồi đúng không? 1. fs.unlinkSync() là gì mà ngầu vậy? Tưởng tượng thế này, các em có một cái "ổ cứng ảo" ngay trong ứng dụng Node.js của mình. Đôi khi, các em tạo ra những file tạm bợ, những dữ liệu không còn cần thiết nữa, giống như mấy cái ảnh chụp màn hình meme sau khi đã gửi cho crush vậy đó. Để giữ cho "ổ cứng" của mình luôn "sạch sẽ" và không bị "rác" chiếm chỗ, chúng ta cần một công cụ để "quẳng" mấy cái file vô giá trị kia đi. Và đó chính là lúc fs.unlinkSync() ra tay! Nó là một hàm trong module fs (File System) của Node.js, dùng để xóa một file khỏi hệ thống. Từ unlink ở đây không phải là "hủy liên kết" đâu nhé, mà nó là thuật ngữ cổ điển trong hệ thống UNIX/Linux để chỉ việc xóa một file (thực chất là gỡ bỏ liên kết đến inode của file đó, nhưng thôi, chuyện đó để sau). Cái từ Sync phía sau mới là điểm đáng chú ý nè. Nó có nghĩa là đồng bộ (synchronous). Khi em gọi fs.unlinkSync(), chương trình của em sẽ đứng hình, chờ đợi cho đến khi file đó được xóa xong xuôi thì mới chịu làm việc khác. Giống như em đang đứng chờ máy giặt xong mới chịu đi phơi đồ vậy đó. Trong lúc chờ, mọi tác vụ khác của chương trình đều bị block (chặn lại). Nghe có vẻ hơi "khó tính" đúng không? Đúng vậy, nó "khó tính" thật, nhưng đôi khi lại rất tiện lợi! Tóm lại: fs.unlinkSync() dùng để xóa một file cụ thể khỏi hệ thống, và nó làm việc đó một cách đồng bộ, tức là mọi thứ khác phải chờ nó làm xong. 2. Code Ví Dụ Minh Họa: Xóa File Cực Gắt! Để các em dễ hình dung, anh Creyt sẽ "tạo hiện trường" và sau đó "dọn dẹp" nó luôn. Đầu tiên, chúng ta sẽ tạo một file tạm, sau đó dùng fs.unlinkSync() để xóa nó đi. Nhớ là phải dùng try...catch để bắt lỗi nhé, không thì Node.js nó "dỗi" là toang ngay! const fs = require('fs'); const path = require('path'); const fileName = 'file_rac_tam_thoi.txt'; const filePath = path.join(__dirname, fileName); // Bước 1: Tạo một file tạm để chúng ta có cái mà xóa try { fs.writeFileSync(filePath, 'Đây là nội dung rác mà anh Creyt tạo ra để xóa.', 'utf8'); console.log(`Đã tạo file: ${fileName}`); // Bước 2: Kiểm tra xem file có tồn tại không trước khi xóa if (fs.existsSync(filePath)) { console.log(`File ${fileName} đang tồn tại. Chuẩn bị xóa...`); // Bước 3: Dùng fs.unlinkSync() để xóa file fs.unlinkSync(filePath); console.log(`Đã xóa file: ${fileName} thành công!`); } else { console.log(`File ${fileName} không tồn tại để xóa. Có vẻ ai đó đã dọn trước rồi.`); } } catch (err) { // Bước 4: Xử lý lỗi nếu có (ví dụ: file không tồn tại, không có quyền xóa) if (err.code === 'ENOENT') { console.error(`Lỗi: File '${fileName}' không tồn tại. Không thể xóa.`); } else if (err.code === 'EPERM') { console.error(`Lỗi: Không có quyền xóa file '${fileName}'.`); } else { console.error(`Đã xảy ra lỗi khi thao tác với file: ${err.message}`); } } // Bước 5: Kiểm tra lại xem file còn tồn tại không if (!fs.existsSync(filePath)) { console.log(`Xác nhận: File ${fileName} đã biến mất khỏi thế gian.`); } else { console.log(`Xác nhận: File ${fileName} vẫn còn đó. Có gì đó sai sai...`); } Khi chạy đoạn code trên, các em sẽ thấy một file file_rac_tam_thoi.txt được tạo ra, sau đó nó sẽ biến mất trong tích tắc. Đó chính là sức mạnh của unlinkSync()! 3. Mẹo Vặt & Best Practices từ "Lão Làng" Creyt Anh Creyt có vài lời khuyên chân thành cho các em khi "sử dụng" unlinkSync(): Sync vs. Async: Cuộc chiến không hồi kết (cho Node.js app): fs.unlinkSync() là đồng bộ, nên nó sẽ block Event Loop của Node.js. Điều này có nghĩa là trong khi nó đang xóa file, server của em sẽ không thể xử lý bất kỳ request nào khác. Trong môi trường web server (như Express, NestJS), việc này là cực kỳ nguy hiểm và có thể làm "chết" ứng dụng của em nếu file lớn hoặc thao tác chậm. Luôn ưu tiên dùng fs.unlink() (phiên bản bất đồng bộ) hoặc fs.promises.unlink() với async/await cho các ứng dụng web hoặc bất kỳ đâu cần hiệu năng cao. unlinkSync chỉ nên dùng cho các script nhỏ, CLI tool, hoặc các tác vụ setup/teardown mà việc blocking không ảnh hưởng lớn. Luôn luôn dùng try...catch, không thì ăn hành!: Giống như ví dụ trên, việc xóa file có thể thất bại vì nhiều lý do (file không tồn tại, không có quyền ghi/xóa, file đang bị ứng dụng khác khóa...). Nếu không có try...catch, chương trình của em sẽ "crash" ngay lập tức. Hãy luôn chuẩn bị tâm lý cho những điều bất ngờ! Quyền lực đi kèm trách nhiệm (và quyền truy cập): Đảm bảo rằng ứng dụng Node.js của em có đủ quyền để xóa file trong thư mục đích. Chạy ứng dụng với quyền "root" hoặc "admin" chỉ khi thực sự cần thiết và hiểu rõ rủi ro, không thì "tự bắn vào chân" đấy. Kiểm tra sự tồn tại của file trước khi xóa: Mặc dù try...catch sẽ bắt lỗi ENOENT (file không tồn tại), việc kiểm tra bằng fs.existsSync() trước khi xóa có thể giúp code của em "sạch" hơn và tránh những lỗi không cần thiết khi file đã bị xóa bởi một tiến trình khác. Hoặc đôi khi, việc file không tồn tại không phải là một lỗi mà là một trạng thái mong muốn. 4. Ứng Dụng Thực Tế: Ai đang dùng unlinkSync()? Trong thế giới thực, fs.unlinkSync() (hoặc phổ biến hơn là fs.unlink() bất đồng bộ) được sử dụng trong rất nhiều tình huống: Dọn dẹp file tạm: Khi người dùng upload ảnh lên server, server có thể tạo ra các phiên bản ảnh đã resize, thumbnail. Sau khi xử lý xong và lưu vào database hoặc cloud storage, các file gốc hoặc file tạm này cần được xóa đi để tiết kiệm dung lượng. Xóa log file cũ: Các hệ thống thường tạo ra log file để ghi lại hoạt động. Để tránh log file phình to vô hạn, các script định kỳ sẽ xóa những log file quá cũ. Cache Invalidation: Khi dữ liệu cache trên disk không còn hợp lệ, hệ thống có thể xóa các file cache đó để buộc ứng dụng phải tạo lại cache mới. Trong các bài kiểm thử (Unit/Integration Tests): Sau khi chạy xong một bộ test, các file tạm hoặc database tạm được tạo ra trong quá trình test cần được dọn dẹp để đảm bảo môi trường sạch sẽ cho lần chạy test tiếp theo. Đây là một case rất hợp lý để dùng unlinkSync trong các hàm afterEach hoặc afterAll của các test framework. Các "ông lớn" như Facebook, Google, TikTok... đều có những hệ thống quản lý file khổng lồ, và chắc chắn họ dùng các phiên bản bất đồng bộ và tối ưu hơn rất nhiều để xử lý việc xóa file hàng tỷ lần mỗi ngày. Còn unlinkSync của chúng ta, nó như một "công cụ" đơn giản nhưng hiệu quả cho những tác vụ nhỏ, cần sự chắc chắn tức thì. 5. Thử Nghiệm của anh Creyt & Khi nào nên dùng? Anh Creyt từng "ngây thơ" thử dùng fs.unlinkSync() để xóa một file log dung lượng vài GB trong một ứng dụng web đang chạy. Kết quả là... server "đứng hình" vài giây, người dùng thì than trời vì trang web không phản hồi. Đúng là "sai một ly, đi một dặm"! Vậy, khi nào thì nên dùng fs.unlinkSync()? Các script CLI (Command Line Interface) đơn giản: Khi bạn viết một script để tự động hóa tác vụ trên máy tính cá nhân, việc blocking Event Loop không phải là vấn đề lớn. Trong các hàm setup/teardown của test: Như đã nói ở trên, trong các framework test (như Jest, Mocha), bạn có thể dùng unlinkSync trong beforeAll, afterAll, beforeEach, afterEach để tạo hoặc dọn dẹp môi trường test. Lúc này, việc blocking chỉ ảnh hưởng đến quá trình test chứ không phải ứng dụng thực tế. Khi bạn chắc chắn rằng việc blocking Event Loop không gây ra vấn đề hiệu năng hoặc trải nghiệm người dùng: Đây là trường hợp hiếm hoi và cần sự hiểu biết sâu sắc về kiến trúc ứng dụng của mình. Tốt nhất là nên tránh trừ khi có lý do cực kỳ chính đáng. Và khi nào thì tuyệt đối không nên dùng fs.unlinkSync()? Trong các HTTP request handler của một ứng dụng web Node.js: Trừ khi đó là một tác vụ cực kỳ nhỏ và nhanh đến mức không thể cảm nhận được độ trễ. Trong bất kỳ hàm callback nào mà bạn mong đợi Event Loop tiếp tục xử lý các tác vụ khác: Ví dụ, trong một vòng lặp lớn, việc gọi unlinkSync nhiều lần sẽ biến ứng dụng của bạn thành "con rùa bò" ngay lập tức. Vậy đó, các em đã thấy fs.unlinkSync() tuy nhỏ nhưng có võ, và quan trọng là phải biết dùng nó đúng lúc, đúng chỗ. Đừng để nó trở thành "thủ phạm" làm chậm ứng dụng của mình nhé! Học lập trình là phải thực tế, phải hiểu rõ công cụ mình đang dùng, chứ không phải cứ thấy hàm là xài bừa đâu. Nhớ lấy lời anh Creyt! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

44 Đọc tiếp
fs.unlink(): Xóa Sổ Files Như Một Pro Trong Node.js!
20/03/2026

fs.unlink(): Xóa Sổ Files Như Một Pro Trong Node.js!

Chào các dân chơi công nghệ, hôm nay anh Creyt sẽ cùng các bạn "mổ xẻ" một "công cụ" cực kỳ quan trọng trong bộ "đồ nghề" của Node.js khi làm việc với hệ thống tệp tin: fs.unlink(). Nghe tên có vẻ hơi "hàn lâm" nhưng thực chất nó lại là một "tay chơi" cực kỳ thực dụng! 1. fs.unlink() là gì và Để Làm Gì? "Unlink" dịch nôm na ra là "gỡ liên kết" hay "xóa bỏ". Trong Node.js, fs.unlink() chính là "chiếc chổi thần kỳ" giúp bạn quét sạch một file ra khỏi hệ thống tệp tin của máy chủ, vĩnh viễn và không một chút hối tiếc. Tưởng tượng thế này: Bạn vừa "phóng" một quả bóng bay lên trời (upload một file lên server). Sau khi quả bóng bay đã hoàn thành sứ mệnh của nó (ví dụ: đã được xử lý, đã được người dùng download xong, hoặc đơn giản là nó bị lỗi và không còn giá trị nữa), bạn không muốn nó cứ "lơ lửng" mãi trên bầu trời server làm "rác" tài nguyên. Lúc này, fs.unlink() chính là "cây kim" thần thánh giúp bạn "chọc" thủng quả bóng bay đó, khiến nó "biến mất" hoàn toàn. Nó giống như việc bạn dọn dẹp phòng sau một bữa tiệc tùng vậy, những thứ không cần thiết nữa thì "out"! Để làm gì ư? Đơn giản là để: Dọn dẹp: Xóa các file tạm, file cache, file log cũ không còn dùng nữa để giải phóng dung lượng ổ đĩa. Bảo mật: Loại bỏ các file chứa dữ liệu nhạy cảm sau khi đã xử lý xong (ví dụ: file chứa thông tin thanh toán tạm thời). Quản lý tài nguyên: Đảm bảo server của bạn luôn "sạch sẽ" và hoạt động hiệu quả, tránh bị "nghẽn cổ chai" vì quá nhiều file rác. 2. Code Ví Dụ Minh Họa Rõ Ràng Trong Node.js, fs.unlink() có hai "phiên bản" chính: bất đồng bộ (asynchronous) và đồng bộ (synchronous). Anh Creyt khuyên dùng bất đồng bộ để tránh "đứng hình" ứng dụng của bạn nhé. A. Phiên bản Bất đồng bộ (Async - Dùng Callback) Đây là cách truyền thống, bạn "giao việc" cho Node.js và bảo nó "khi nào làm xong thì báo anh một tiếng nhé". const fs = require('fs'); const filePath = './my_temp_file.txt'; // Bước 1: Tạo một file tạm để chúng ta có cái mà xóa fs.writeFile(filePath, 'Đây là nội dung của file tạm cần xóa.', (err) => { if (err) { console.error('Lỗi khi tạo file:', err); return; } console.log('File tạm đã được tạo thành công.'); // Bước 2: Sử dụng fs.unlink để xóa file fs.unlink(filePath, (err) => { if (err) { // Rất quan trọng: Luôn xử lý lỗi! // Ví dụ: file không tồn tại, không có quyền xóa... if (err.code === 'ENOENT') { console.error('Lỗi: File không tồn tại để xóa.'); } else { console.error('Lỗi khi xóa file:', err); } return; } console.log('File đã được xóa thành công!'); }); }); B. Phiên bản Bất đồng bộ (Async - Dùng Promises/Async-Await) Đây là cách hiện đại và "ngầu" hơn, giúp code của bạn dễ đọc và dễ quản lý lỗi hơn, đặc biệt khi có nhiều thao tác nối tiếp nhau. Anh em Genz chắc chắn sẽ thích cái này! const fs = require('fs').promises; // Lấy phiên bản promise của fs const filePath = './another_temp_file.txt'; async function deleteMyFile() { try { // Bước 1: Tạo file tạm await fs.writeFile(filePath, 'Nội dung file này sẽ bị xóa sau.'); console.log('File tạm đã được tạo thành công.'); // Bước 2: Xóa file await fs.unlink(filePath); console.log('File đã được xóa thành công với Promises!'); } catch (err) { // Bắt lỗi tập trung ở đây! if (err.code === 'ENOENT') { console.error('Lỗi: File không tồn tại để xóa.'); } else { console.error('Lỗi khi xóa file:', err); } } } deleteMyFile(); C. Phiên bản Đồng bộ (Sync - fs.unlinkSync) Cái này thì "nhanh gọn lẹ" nhưng có thể làm "đứng tim" ứng dụng của bạn nếu file quá lớn hoặc hệ thống bận. Chỉ nên dùng khi bạn biết chắc chắn không ảnh hưởng đến hiệu suất, ví dụ trong các script nhỏ hoặc khởi tạo ứng dụng. const fs = require('fs'); const filePath = './sync_temp_file.txt'; try { // Bước 1: Tạo file tạm fs.writeFileSync(filePath, 'Nội dung file này sẽ bị xóa đồng bộ.'); console.log('File tạm đồng bộ đã được tạo.'); // Bước 2: Xóa file đồng bộ fs.unlinkSync(filePath); console.log('File đã được xóa đồng bộ thành công!'); } catch (err) { // Xử lý lỗi if (err.code === 'ENOENT') { console.error('Lỗi: File đồng bộ không tồn tại để xóa.'); } else { console.error('Lỗi khi xóa file đồng bộ:', err); } } 3. Mẹo (Best Practices) Từ Anh Creyt Để "Xóa Sạch" Không "Dấu Vết" Luôn Luôn Xử Lý Lỗi (Error Handling): Đây là "chân lý" khi làm việc với file system. File có thể không tồn tại, bạn có thể không có quyền xóa, hoặc ổ đĩa đầy. Nếu không xử lý, ứng dụng của bạn sẽ "sập" không thương tiếc. Cẩn Thận Với Đường Dẫn (Path): Kiểm tra kỹ đường dẫn file trước khi xóa. Xóa nhầm file hệ thống là "xong phim" đấy, không có "Ctrl+Z" đâu! Async Là Bạn Tốt: Ưu tiên dùng phiên bản fs.promises.unlink hoặc callback fs.unlink để đảm bảo ứng dụng của bạn không bị "đứng hình" (blocking) khi chờ đợi thao tác xóa file. "Soft Delete" (Xóa Mềm) Cho Dữ Liệu Quan Trọng: Đối với dữ liệu người dùng hoặc các file quan trọng mà bạn có thể cần phục hồi, đừng dùng fs.unlink() ngay lập tức. Thay vào đó, hãy "đánh dấu" file đó là đã xóa trong cơ sở dữ liệu và chỉ xóa vật lý sau một thời gian nhất định hoặc khi có yêu cầu rõ ràng. Như kiểu bạn chuyển đồ vào thùng rác nhưng chưa đổ đi ngay ấy. Kiểm Tra Quyền Hạn: Đảm bảo rằng tiến trình Node.js của bạn có đủ quyền để xóa file trong thư mục đó. Nếu không, bạn sẽ nhận lỗi EACCES (Permission denied). 4. Ứng Dụng Thực Tế Nào Đã Dùng fs.unlink()? fs.unlink() là một "người hùng thầm lặng" xuất hiện trong rất nhiều hệ thống mà bạn dùng hàng ngày: Ứng dụng Upload File (ví dụ: Google Drive, Dropbox): Khi bạn upload một file mới và sau đó quyết định xóa nó, hoặc khi bạn upload một ảnh đại diện mới và ảnh cũ bị thay thế, fs.unlink() sẽ được dùng để dọn dẹp file cũ trên server. Hệ thống Quản lý Ảnh/Video (ví dụ: Instagram, TikTok): Khi bạn chỉnh sửa ảnh/video, các phiên bản tạm thời, hoặc các file gốc sau khi đã được xử lý và lưu dưới định dạng tối ưu sẽ được xóa đi. Các nền tảng CMS (Content Management System - ví dụ: WordPress): Khi bạn xóa một bài viết kèm ảnh, hoặc xóa một plugin/theme, các file liên quan trên server sẽ được fs.unlink() dọn dẹp. Hệ thống Log Server: Các server thường tạo ra rất nhiều file log. Định kỳ, các file log cũ sẽ được fs.unlink() xóa đi để tránh làm đầy ổ đĩa. Cache Server: Các file cache hết hạn hoặc không còn giá trị sẽ được xóa để giải phóng bộ nhớ và đảm bảo dữ liệu luôn tươi mới. 5. Thử Nghiệm Đã Từng và Nên Dùng Cho Case Nào? Anh Creyt đã từng "thử nghiệm" với fs.unlink() trong nhiều dự án khác nhau và rút ra vài kinh nghiệm xương máu: Nên dùng fs.unlink() khi: Xóa file tạm: Các file được sinh ra để phục vụ một tác vụ nhất thời (ví dụ: file PDF được tạo ra để người dùng download rồi xóa đi). Xóa file cache: Các file cache đã hết hạn hoặc không còn hợp lệ. Xóa file log cũ: Quản lý vòng đời của các file log để tránh đầy ổ đĩa. Thay thế file: Khi người dùng upload một phiên bản mới của một file (ví dụ: ảnh đại diện), file cũ cần được xóa. Dọn dẹp sau khi xử lý: Ví dụ, bạn nhận được một file zip, giải nén nó, xử lý các file bên trong, và sau đó xóa file zip gốc. Không nên dùng fs.unlink() một cách "vô tội vạ" khi: Dữ liệu có khả năng cần phục hồi: Nếu file đó là dữ liệu người dùng quan trọng và có thể cần "quay lại" trong tương lai, hãy cân nhắc "soft delete" (đánh dấu xóa trong DB) thay vì xóa vật lý ngay lập tức. Bạn không chắc chắn về đường dẫn: Như đã nói, xóa nhầm là "đi tong" cả hệ thống. Luôn kiểm tra kỹ. Nhớ nhé các bạn, fs.unlink() là một "tay đấm" mạnh mẽ, nhưng cũng cần được sử dụng một cách thông minh và có trách nhiệm để server của chúng ta luôn "khỏe mạnh" và "sạch sẽ"! Thuộc Series: Nodejs Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

40 Đọc tiếp