當你輸入一個url時,這個url可能對應服務器上的一個資源(文件)也可能對應一個目錄。 So服務器會對這個url進行分析,針對不同的情況做不同的事。 如果這個url對應的是一個文件,那么服務器就會返回這個文件。 如果這個url對應的是一個文件夾,那么服務器會返回這個文件夾下包含的所有子文件/子文件夾的列表。 以上,就是一個靜態服務器所主要干的事。
但真實的情況不會像這么簡單, 我們所拿到的url可能是錯誤的,它所對應的文件或則文件夾或許根本不存在, 又或則有些文件和文件夾是被系統保護起來的是隱藏的,我們并不想讓客戶端知道。 因此,我們就要針對這些特殊情況進行一些不同的返回和提示。
再者,當我們真正返回一個文件前,我們需要和客戶端進行一些協商。 我們需要知道客戶端能夠接受的語言類型、編碼方式等等以便針對不同瀏覽器進行不同的返回處理。 我們需要告訴客戶端一些關于返回文件的額外信息,以便客戶端能更好的接收數據: 文件是否需要緩存,該怎樣緩存? 文件是否進行了壓縮處理,該以怎樣的方式解壓? 等等...
至此,我們已經初步了解了一個靜態服務器所主要做的幾乎所有事情, let's go!
實現
項目目錄
static-server/|| - bin/| | - start # 批處理文件| || - src/| | - App.js # main文件| | - Config.js # 默認配置||·- package.json
配置文件
要啟動一個服務器,我們需要知道這個服務器的啟動時的端口號和靜態服務器的工作目錄
let config = { host:'localhost' //提升用 ,port:8080 //服務器啟動時候的默認端口號 ,path:path.resolve(__dirname,'..','test-dir') //靜態服務器啟動時默認的工作目錄}整體框架
注意
事件函數中的this默認指向綁定的對象(這里是小server),這里修改成了Server這個大對象,以便調用在回調函數中調用Server下的方法。
class Server(){ constructor(options){ /* === 合并配置參數 === */ this.config = Object.assign({},config,options) } start(){ /* === 啟動http服務 === */ let server = http.createServer(); server.on('request',this.request.bind(this)); server.listen(this.config.port,()=>{ let url = `${this.config.host}:${this.config.port}`; console.log(`server started at ${chalk.green(url)}`) }) } async request(req,res){ /* === 處理客戶端請求,決定響應信息 === */ // try //如果是文件夾 -> 顯示子文件、文件夾列表 //如果是文件 -> sendFile() // catch //出錯 -> sendError() } sendFile(){ //對要返回的文件進行預處理并發送文件 } handleCache(){ //獲取和設置緩存相關信息 } getEncoding(){ //獲取和設置編碼相關信息 } getStream(){ //獲取和設置分塊傳輸相關信息 } sendError(){ //錯誤提示 }}module.exports = Server;
新聞熱點
疑難解答
圖片精選