静态服务器搭建

目的

手写简易版搭建一个既能提供静态文件,又能处理动态路由mock数据的服务器。

前提

会用到nodejs的几个内置模块:

var http = require('http') //启动server
var fs = require('fs') //读取文件
var path = require('path') //处理路径
var url = require('url') //解析请求url的信息

一. 入口,server.js:

var http = require('http')
http.createServer((request, response)=>{
    response.setHeader('Content-Type','text/html;charset=utf-8')
    response.writeHead(200,'success')//响应状态码
    response.write('<body>')
    response.write('<h1>你好</h1>')
    response.write('</body>')
    response.end()
})
http.listen(8888)//自定义端口号
  • 本地启动:node server.js
  • 浏览器访问:http://localhost:8888/
  • 响应response.write里面的内容并展示在浏览器:代码为<body><h1>你好</h1></body>

二、获取静态文件

在以上基础上,如果将响应内容<body><h1>你好</h1></body>替换成脚本文件,就需要获取文件路径,然后读取到文件内容

  1. 获取文件路径:
    var filePath = path.join(path.join(__dirname, 'static'), url.parse(req.url).pathname)

    • __dirname:当前文件路径;
    • path.join(__dirname, 'static'),nodejs内置模块'path',path.join(__dirname, 'static'),用path.join()拼接路径是为了统一路径的不同写法并得到一个绝对路径static作为脚本文件的文件夹名;
      目录结构
      • url.parse(req.url).pathname,解析出url的相关信息,pathname为脚本文件名。
  2. 读取文件内容:

     // var fileContent = fs.readFileSync(filePath,'binary') //同步读取
    
     fs.readFile(filePath, "binary", function(err, fileContent){   //异步读取
         if(err){
             resp.writeHead(404, "not found yeah")
             resp.end('<h1>not found</h1>')
         }else{
             resp.writeHead(200, "success")
             resp.write(fileContent, "binary")
             resp.end()
         }
     })
    
  3. 完整代码:

        var http = require('http')
        var path = require('path') //统一路径写法
        var fs = require('fs')  //获取文件信息
        var url = require('url') //解析url的信息
    
        var server = http.createServer(function(req, resp){
            if(url.parse(req.url).pathname === "/favicon.ico"){
                return
            }
            staticRoot(path.join(__dirname, 'static'), req, resp)
        }).listen(8888)
    
        function staticRoot(staticPath, req, resp){
            var pathObj = url.parse(req.url)
            if(pathObj.pathname === '/'){
                pathObj.pathname += "index.html"
            }
            var filePath = path.join(staticPath, pathObj.pathname)
            // var fileContent = fs.readFileSync(filePath,'binary') //同步读取
            fs.readFile(filePath, "binary", function(err, fileContent){   //异步读取
                if(err){
                    resp.writeHead(404, "not found yeah")
                    resp.end('<h1>not found</h1>')
                }else{
                    resp.writeHead(200, "success")
                    resp.write(fileContent, "binary")
                    resp.end()
                }
            })
        }
    

    以上,包括对应的css、js、imgs文件也能获取到。

三、处理动态路由

当然,到第二步已经能获取响应脚本文件,但也有接口请求的情况或者需要mock数据,这时需要根据请求的不同url给出不同的响应,而非读取脚本文件。
既能提供静态文件,又能处理动态路由

  • 思路:首先给出一个路由表,解析出不同请求的url里面url.parse(request.url).pathname如果存在路由表的对应路径,就转而处理对应路径的函数,否则就回到第二步,继续去读取响应脚本文件。
  • 完整代码:
     var http = require('http')
     var fs = require('fs')
     var path = require('path')
     var url = require('url')

     var routes = {
         '/a': function (req, resp) {
             // resp.setHeader('Content-Type','text/js;charset=utf-8')
             // resp.end(JSON.stringify(req.query))
             resp.end(JSON.stringify(req.body))
         },
         '/b': function (req, resp) {

         },
         '/c': function (req, resp) {

         }
     }

     http.createServer(function (request, response) {
         if (url.parse(request.url).pathname === '/favicon.ico') {
             response.end()
         } else {
             rootPath(request, response)
         }
     }).listen(8080)

     function rootPath(request, response) {
         var pathObj = url.parse(request.url)
         var routeFn = routes[pathObj.pathname]
         if (routeFn) {
             request.query = pathObj.query //GET数据

             var body = ''
             request.on('data', function (chunk) {
                 body += chunk
             }).on('end', function () {
                 request.body = parseBody(body) //POST数据 
                 routeFn(request, response)
             })
         } else {
             rootStatic(request, response)
         }
     }

     //将字符串'a=1&b=2'转换为对象{a:1, b:2}
     function parseBody(body) { 
         var bodyObj = {}
         body.split('&').forEach(function (cont) {
             bodyObj[cont.split('=')[0]] = cont.split('=')[1]
         })
         return bodyObj
     }


     function rootStatic(request, response) {
         var pathName = url.parse(request.url).pathname

         if (pathName === '/') {
             pathName += 'index.html'
         }

         pathName = path.join('static', pathName)
         var filePath = path.join(__dirname, pathName)
         fs.readFile(filePath, 'binary', function (err, content) {
             if (err) {
                 response.writeHead(404, "not found")
                 response.end('not found')
             } else {
                 response.writeHead(200, 'success yes')
                 response.write(content, 'binary')
                 response.end()
             }
         })
     }   

源码地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容