深入掌握Node.js HTTP模塊:從開始到放棄

文章目錄

  • 一、HTTP模塊入門:從零搭建第一個服務器
    • 1.1 基礎概念解析
    • 1.2 手把手創建服務器
  • 二、核心功能深入解析
    • 2.1 處理不同請求類型
    • 2.2 實現文件下載功能
  • 三、常見問題解決方案
    • 3.1 跨域問題處理
    • 3.2 防止服務崩潰
    • 3.3 調試技巧
  • 四、安全最佳實踐
    • 4.1 請求頭安全設置
    • 4.2 速率限制(防止DDoS攻擊)
  • 五、簡易版博客系統
    • 5.1 項目結構
    • 5.2 環境準備
    • 5.3 核心代碼實現

一、HTTP模塊入門:從零搭建第一個服務器

1.1 基礎概念解析

HTTP 模塊是什么?
Node.js內置的 http 模塊提供了創建 HTTP 服務器和客戶端的能力。就像快遞公司:

  • 服務器:像倉庫,存儲貨物(數據)
  • 客戶端:像快遞員,負責收發貨物(請求和響應)

核心對象解釋:

  • http.createServer:創建服務器
  • req對象:包含客戶端請求的信息(地址、請求頭等)
  • res對象:用來給客戶端發送響應

1.2 手把手創建服務器

// 導入模塊(類似取快遞工具)
const http = require('http');// 創建服務器(建立倉庫)
const server = http.createServer((req, res) => {// 設置響應頭(告訴快遞員包裹類型)res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); // 明確指定編碼,不然運行之后是亂碼// 發送響應內容(實際運送的貨物)res.end('<h1>歡迎來到我的網站!</h1>');
})// 啟動監聽(設置倉庫門牌號)
server.listen(3000, () => {console.log('服務器已在 http://localhost:3000 啟動')
})

二、核心功能深入解析

2.1 處理不同請求類型

GET 請求參數獲取

const { URL } = require('url');server.on('request', (req, res) => {// 解析URL(類似拆包裹看地址標簽)const urlObj = new URL(req.url, `http://${req.headers.host}`);// 獲取查詢參數(比如?name=John)console.log(urlObj.searchParams.get('name')); // 輸出 John
})

POST 請求數據處理

let body = [];
req.on('data', chunk => {body.push(chunk); //接收數據塊(像接收多個包裹)
}).on('end', () => {body = Buffer.concat(body).toString(); // 合并所有數據塊console.log('收到POST數據:', body);
})

2.2 實現文件下載功能

const fs = require('fs');function downloadFile(res, filePath) {// 設置響應頭(高速瀏覽器這是要下載的文件)res.writeHead(200, {'Content-Type': 'application/octet-stream','Content-Disposition': `attachment; filename=${path.basename(filePath)}`});// 創建文件流(像打開水龍頭放水)const fileStream = fs.createReadStream(filePath);fileStream.pipe(res); // 將文件流導向響應
}

三、常見問題解決方案

3.1 跨域問題處理

// 在響應頭中添加CORS支持
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

3.2 防止服務崩潰

// 全局錯誤捕獲
process.on('uncaughtException', (err) => {console.error('全局異常捕獲:', err);// 可以記錄日志或發送警報
});// 處理Promise拒絕
process.on('unhandledRejection', (reason, promise) => {console.error('未處理的Promise拒絕:', reason);
});

3.3 調試技巧

使用 curl 測試接口:

# 測試GET請求
curl http://localhost:3000/api/data# 測試POST請求
curl -X POST -d "username=john" http://localhost:3000/login

四、安全最佳實踐

4.1 請求頭安全設置

res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "default-src 'self'");

4.2 速率限制(防止DDoS攻擊)

const rateLimit = require('express-rate-limit');const limiter = rateLimit({windowMs: 15 * 60 * 1000, // 15分鐘max: 100 // 每個IP最多100次請求
});// 應用中間件
server.use(limiter);

五、簡易版博客系統

5.1 項目結構

/my-blog
├── data/            # 數據存儲
│   └── articles.json
├── public/          # 靜態資源
│   ├── css/
│   └── js/
│   └── index.html
├── controllers/     # 業務邏輯
│   └── articleController.js
├── routes/          # 路由配置
│   └── articleRoutes.js
├── utils/           # 工具函數
│   └── fileUtils.js
└── server.js        # 入口文件

5.2 環境準備

1.初始化項目

mkdir my-blog && cd my-blog
npm init -y

2.安裝依賴

npm install uuid      # 生成唯一ID

5.3 核心代碼實現

1.數據存儲(data/articles.json)

{"articles": [{"id": "1","title": "Node.js入門指南","content": "Node.js是一個基于Chrome V8引擎的JavaScript運行環境...","createdAt": "2023-08-20"}]
}

2.工具函數(utils/fileUtils.js)

const fs = require('fs').promises;
const path = require('path');const dataPath = path.join(__dirname, '../data/articles.json');async function readData() {try {const data = await fs.readFile(dataPath, 'utf8');return JSON.parse(data);} catch (err) {return { articles: [] };}
}async function writeData(data) {await fs.writeFile(dataPath, JSON.stringify(data, null, 2));
}module.exports = { readData, writeData };

3. 控制器(controllers/articleController.js)

const { v4: uuidv4 } = require('uuid');
const { readData, writeData } = require('../utils/fileUtils');// 獲取所有文章
async function getAllArticles() {const data = await readData();return data.articles;
}// 創建新文章
async function createArticle(title, content) {const data = await readData();const newArticle = {id: uuidv4(),title,content,createdAt: new Date().toISOString().split('T')[0]};data.articles.push(newArticle);await writeData(data);return newArticle;
}// 刪除文章
async function deleteArticle(id) {const data = await readData();data.articles = data.articles.filter(article => article.id !== id);await writeData(data);
}module.exports = { getAllArticles, createArticle, deleteArticle };

4. 路由配置(routes/articleRoutes.js)

const http = require('http');
const fs = require('fs');
const path = require('path');// 假設這是文章數據存儲
let articles = [];
let nextId = 1;function handleRoutes(req, res) {const urlParts = req.url.split('/');if (req.url === '/api/articles' && req.method === 'GET') {res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify(articles));} else if (req.url === '/api/articles' && req.method === 'POST') {let body = '';req.on('data', chunk => {body += chunk.toString();});req.on('end', () => {const newArticle = JSON.parse(body);newArticle.id = nextId++;articles.push(newArticle);res.writeHead(201, { 'Content-Type': 'application/json' });res.end(JSON.stringify(newArticle));});} else if (urlParts[1] === 'api' && urlParts[2] === 'articles' && req.method === 'DELETE') {if (urlParts.length === 3) {// 批量刪除articles = [];res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ message: '所有文章刪除成功' }));} else {// 單篇刪除const id = parseInt(urlParts[3]);const index = articles.findIndex(article => article.id === id);if (index !== -1) {articles.splice(index, 1);res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ message: '文章刪除成功' }));} else {res.writeHead(404, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ message: '文章未找到' }));}}} else {res.writeHead(404, { 'Content-Type': 'text/plain' });res.end('Not Found');}
}module.exports = handleRoutes;

5. 主服務器(server.js)

const http = require('http');
const fs = require('fs');
const path = require('path');
const handleRoutes = require('./routes/articleRoutes');// 創建HTTP服務器
const server = http.createServer(async (req, res) => {// 靜態文件服務if (req.url.startsWith('/public/')) {const filePath = path.join(__dirname, req.url);fs.readFile(filePath, (err, data) => {if (err) {res.writeHead(404);return res.end('File not found');}res.writeHead(200);res.end(data);});return;}// API路由處理handleRoutes(req, res);
});// 啟動服務器
const PORT = 3000;
server.listen(PORT, () => {console.log(`Server running at http://localhost:${PORT}`);
});

6.頁面樣式跟邏輯

// public/js/app.js
// 加載文章列表的函數
async function loadArticles() {try {const response = await fetch('/api/articles');if (!response.ok) {throw new Error('網絡響應失敗');}const articles = await response.json();const articlesDiv = document.getElementById('articles');articlesDiv.innerHTML = '';articles.forEach(article => {const articleElement = document.createElement('div');articleElement.innerHTML = `<h2>${article.title}</h2><p>${article.content}</p><button onclick="deleteArticle('${article.id}')">刪除文章</button>`;articlesDiv.appendChild(articleElement);});} catch (error) {console.error('加載文章列表時出錯:', error);}
}// 刪除文章的函數
async function deleteArticle(id) {try {const response = await fetch(`/api/articles/${id}`, {method: 'DELETE'});if (!response.ok) {throw new Error('刪除文章失敗');}// 重新加載文章列表loadArticles();} catch (error) {console.error('刪除文章時出錯:', error);}
}// 添加文章的函數
async function addArticle(event) {event.preventDefault();const title = document.getElementById('title').value;const content = document.getElementById('content').value;try {const response = await fetch('/api/articles', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ title, content })});if (!response.ok) {throw new Error('添加文章失敗');}// 清空表單document.getElementById('articleForm').reset();// 重新加載文章列表loadArticles();} catch (error) {console.error('添加文章時出錯:', error);}
}// 頁面加載完成后自動加載文章列表
window.addEventListener('DOMContentLoaded', loadArticles);
// public/index.html
<!DOCTYPE html>
<html>
<head><!-- 添加字符編碼聲明 --><meta charset="UTF-8"><title>我的博客</title><link rel="stylesheet" href="/public/css/style.css">
</head>
<body><div id="app"><h1>文章列表</h1><!-- 修改文章表單,移除文件輸入框 --><form id="articleForm" onsubmit="addArticle(event)"><input type="text" id="title" placeholder="文章標題" required><textarea id="content" placeholder="文章內容" required></textarea><button type="submit">添加文章</button></form><div id="articles"></div><button onclick="loadArticles()">刷新列表</button></div><script src="/public/js/app.js"></script>
</body>
</html>
// public/css/style.css
body {font-family: Arial, sans-serif;line-height: 1.6;margin: 0;padding: 0;background-color: #f4f4f4;
}#app {width: 80%;margin: auto;overflow: hidden;padding: 20px;
}h1 {color: #333;text-align: center;
}#articleForm {background-color: #fff;padding: 20px;margin-bottom: 20px;border-radius: 5px;box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}#articleForm input[type="text"],
#articleForm textarea {width: 100%;padding: 10px;margin-bottom: 10px;border: 1px solid #ddd;border-radius: 3px;
}#articleForm button {background-color: #333;color: #fff;padding: 10px 20px;border: none;border-radius: 3px;cursor: pointer;
}#articleForm button:hover {background-color: #555;
}#articles div {background-color: #fff;padding: 20px;margin-bottom: 10px;border-radius: 5px;box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}#articles h2 {margin-top: 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82573.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82573.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82573.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SSM整合:Spring+SpringMVC+MyBatis完美融合實戰指南

前言 在Java企業級開發領域&#xff0c;SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架組合一直占據著重要地位。這三個輕量級框架各司其職又相互配合&#xff0c;為開發者提供了高效、靈活的開發體驗。本文將深入探討SSM框架的整合過程&#xff0c;揭示整合背后的原…

[AI]大模型MCP快速入門及智能體執行模式介紹

[AI]大模型MCP快速入門及智能體執行模式介紹 一、MCP入門 介紹 MCP&#xff08;Model Context Protocol&#xff0c;模型上下文協議&#xff09;是一種由Anthropic公司于2024年提出的開放標準協議&#xff0c;旨在為大型語言模型&#xff08;LLM&#xff09;提供統一接口&am…

Mac M1 安裝 ffmpeg

1.前言 官網那貨沒有準備m系列的靜態包&#xff0c;然后我呢&#xff0c;不知道怎么想的就從maven項目中的 javacv-platform&#xff0c;且版本為1.5.11依賴里面將這個靜態包把了出來&#xff0c;親測能用&#xff0c;感覺比那些網上說的用什么wget編譯安裝、brew安裝快多了。…

unity控制相機圍繞物體旋轉移動

記錄一下控制相機圍繞物體旋轉與移動的腳本&#xff0c;相機操作思路分為兩塊&#xff0c;一部分為旋轉&#xff0c;一部分為移動&#xff0c;旋轉是根據當前center中心點的坐標&#xff0c;根據距離設置與默認的旋轉進行位置移動&#xff0c;移動是根據相機的左右和前后進行計…

python打卡day38@浙大疏錦行

知識點回顧&#xff1a; Dataset類的__getitem__和__len__方法&#xff08;本質是python的特殊方法&#xff09;Dataloader類minist手寫數據集的了解 作業&#xff1a;了解下cifar數據集&#xff0c;嘗試獲取其中一張圖片 一、首先加載CIFAR數據集 import torch import torchvi…

用戶配置文件(Profile)

2.4.5 用戶配置文件&#xff08;Profile&#xff09; 用戶配置文件由以下組件構成&#xff1a; 一個運營商安全域&#xff08;MNO-SD&#xff09; 輔助安全域&#xff08;SSD&#xff09;和CASD Applets 應用程序&#xff08;如NFC應用&#xff09; 網絡接入應用&#xff…

如何給自研MCP加上安全驗證

前言 剛過去兩個月,市面的 MCP 服務,如雨后春筍一般不斷涌現出來,包括;百度、高德、網盤、支付寶。這些 MCP 服務,可以讓我們基于 Spring AI 框架構建的 Agent 具備非常豐富的使用功能。同時這也說明,程序員???????,應該具備開發 MCP 服務的能力,Spring AI 讓 J…

Unity網絡開發實踐項目

摘要&#xff1a;該網絡通信系統基于Unity實現&#xff0c;包含以下幾個核心模塊&#xff1a; 協議配置&#xff1a;通過XML定義枚舉&#xff08;如玩家/英雄類型&#xff09;、數據結構&#xff08;如PlayerData&#xff09;及消息協議&#xff08;如PlayerMsg&#xff09;&a…

OpenCV CUDA模塊圖像過濾------創建一個 Sobel 濾波器函數createSobelFilter()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數用于創建一個 Sobel 濾波器&#xff0c;用于在 GPU 上進行邊緣檢測。它基于圖像的梯度計算&#xff1a; dx 表示對 x 方向求導的階數&…

【JavaSE】枚舉和注解學習筆記

枚舉和注解 -枚舉 規定多選一數據類型的解決方案-枚舉 枚舉對應英文(enumeration,簡寫 enum) 2)枚舉是一組常量的集合。 3)可以這里理解:枚舉屬于一種特殊的類&#xff0c;里面只包含一組有限的特定的對象。 枚舉的兩種實現方式 自定義實現枚舉 使用enum關鍵字實現枚舉 自…

Spark SQL進階:解鎖大數據處理的新姿勢

目錄 一、Spark SQL&#xff0c;為何進階&#xff1f; 二、進階特性深剖析 2.1 窗口函數&#xff1a;數據洞察的新視角 2.2 高級聚合&#xff1a;挖掘數據深度價值 2.3 自定義函數&#xff08;UDF 和 UDTF&#xff09;&#xff1a;拓展功能邊界 三、性能優化實戰 3.1 數…

如何利用 Conda 安裝 Pytorch 教程 ?

如何利用 Conda 安裝 Pytorch 教程 &#xff1f; 總共分為六步走&#xff1a; &#xff08;1&#xff09;第一步&#xff1a;驗證conda 環境是否安裝好&#xff1f; 1) conda -V2) conda --version&#xff08;2&#xff09;第二步&#xff1a;查看現有環境 conda env list…

什么是HTTP

HTTP&#xff08;HyperText Transfer Protocol&#xff09;是萬維網數據通信的基礎協議&#xff0c;作為應用層協議具有以下關鍵特性&#xff1a; 客戶端-服務器模型&#xff1a;基于請求/響應模式 無狀態協議&#xff1a;默認不保留通信狀態 可擴展性&#xff1a;通過首部字…

2025-05-27 學習記錄--Python-模塊

合抱之木&#xff0c;生于毫末&#xff1b;九層之臺&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、模塊 ?? &#xff08;一&#xff09;模塊的導入與使用 &#x1f36d; 模塊的導入&#xff1a;&#x1f41d; 模塊 就好比…

leetcode 131. Palindrome Partitioning

目錄 一、題目描述 二、方法1、回溯法每次暴力判斷回文子串 三、方法2、動態規劃回溯法 一、題目描述 分割回文子串 131. Palindrome Partitioning 二、方法1、回溯法每次暴力判斷回文子串 class Solution {vector<vector<string>> res;vector<string>…

重構開發范式!飛算JavaAI革新Spring Cloud分布式系統開發

分布式系統憑借高可用性、可擴展性等核心優勢&#xff0c;成為大型軟件項目的標配架構。Spring Cloud作為Java生態最主流的分布式開發框架&#xff0c;雖被廣泛應用于微服務架構搭建&#xff0c;但其傳統開發模式卻面臨效率瓶頸——從服務注冊中心配置到網關路由規則編寫&#…

python 生成復雜表格,自動分頁等功能

py&#xff54;&#xff48;&#xff4f;&#xff4e; 生成復雜表格&#xff0c;自動分頁等功能 解決將Python中的樹形目錄數據轉換為Word表格&#xff0c;并生成帶有合并單元格的檢測報告的問題。首先&#xff0c;要解決“tree目錄數據”和“Word表格互換”&#xff0c;指將樹…

根據Cortex-M3(包括STM32F1)權威指南講解MCU內存架構與如何查看編譯器生成的地址具體位置

首先我們先查看官方對于Cortex-M3預定義的存儲器映射 1.存儲器映射 1.1 Cortex-M3架構的存儲器結構 內部私有外設總線&#xff1a;即AHB總線&#xff0c;包括NVIC中斷&#xff0c;ITM硬件調試&#xff0c;FPB, DWT。 外部私有外設總線&#xff1a;即APB總線&#xff0c;用于…

Linux中硬件信息查詢利器——lshw命令詳解!

lshw&#xff08;List Hardware&#xff09;是 Linux 系統下的一款命令行工具&#xff0c;用于全面檢測并顯示詳細的硬件信息。它能夠報告 CPU、內存、主板、存儲設備、顯卡、網絡設備等幾乎所有硬件組件的詳細信息&#xff0c;適用于系統管理、故障排查和硬件兼容性檢查等場景…

用llama3微調了一個WiFiGPT 用于室內定位

一段話總結 本文提出WiFiGPT,一種基于Decoder-Only Transformer(如LLaMA 3)的室內定位系統,通過將WiFi遙測數據(如CSI、FTM、RSSI)轉換為文本序列進行端到端訓練,無需手工特征工程即可實現高精度定位。實驗表明,WiFiGPT在LOS環境中實現亞米級精度(MAE低至0.90米),在…