#hello,JS:13-03如何搭建服务器

(一)实例一:写一个简单的服务器

一、nodejs写服务器

1、下载github代码

2、开始操作:

(1)分析项目文件step0中的文件index.js,代码如下:

var http = require('http')//是nodejs的内置模块——http(服务器)

即nodejs通过require加载一个模块(一个对象,提供了一些方法能够实现所需要的功能),服务器的底层是由这个nodejs的http模块实现

(2)回到项目文件,用nodejs的内置模块创建一个server:

http.createServer(function(req , res){

})//内含一个回调函数

以上函数实质上内部是一个异步过程,内部可以创建一个服务器,以这个函数作为对应的参数去处理请求。

当浏览器去访问这个服务器的时候,该请求底层会被封装成一个对象。
一个对象:参数req(随意取名),即用户请求的信息都存在这个req对象中,通过获取req得到相关的信息数据(如用户IP、域名,以及一些浏览器的域名等等)
另一个对象:参数res,即需要返回给用户哪些东西

(3)最终在项目文件中创建一个有着基本设置的服务器
代码如下:

//index.js

var http = require('http')
var server = http.createServer(function(req, res){
    console.log(req)         //用户请求所附带的信息
    res.write('hello world') //返回浏览器自带的一些信息
    res.end()
})
server.listen(9000)  //用listen启动这个静态服务器

(4)终端启动:

$ node index.js

此时终端进入一个空白状态(输入无用),即服务器处于一个启动状态,等待用户输入

(5)浏览器输入服务器地址:localhost:9000 (地址不一定一样,端口号自己弄)
出现如图:


image

同时,终端相应出现req这个对象所附带的用户请求的信息(随意截图)


image

注:事实上,console.log所执行的请求数据,除了可以是设定好的参数req,也可以是任意字符串,或者包含数据的json数据等等(不演示了)

至此,写了一个简单的服务器

延伸:解析一下响应体如何进入服务器——服务器处理请求——返回数据:

拿 res.write('hello world')举例:
res.write(即一个响应体)是把数据(即'helloworld')放到http的response响应体里(即响应内容里)

当我们代码请求后输入url发出网络请求,请求时浏览器自动添加响应头相关信息,请求发至服务器之后,则会开始执行以下代码:【这里就是开发者开发不同页面的个性创造所在】

var server = http.createServer(function(req, res){
    console.log(req)         //用户请求所附带的信息
    res.write('hello world') //返回浏览器带的信息(即响应体,页面展现的内容)
    res.end()
})

该服务器发了一个响应res(response),此时服务器后台出现响应头(一些浏览器默认参数),如图:


响应头

响应体对应代码中,则res所请求的内容,这里是'hello world':


响应体

总结,这是网站后台的一个基本逻辑

3、扩展:设置响应头

通过res.setHeader()设置响应头,如可添加:

res.setHeader("Content-Type","text/plain; charset=utf-8")

//text/plain  表示返回内容用字符串(明文)去呈现或者当成html渲染,如text/html
//charset=gbk  表示返回的内容用gbk解码,也可设置为charset=utf-8解码

即项目文件代码为:

//index.js

var http = require('http')
var server = http.createServer(function(req, res){
    console.log('jiengu')//服务器响应的内容
    res.setHeader("Content-Type","text/plain; charset=utf-8")
    res.write('你好世界')//响应体:页面展现的内容
    res.end()
})
server.listen(9000)

重启终端:

$ node index.js

服务器后台响应头设置相应参数后,出现如图:

image

注意: 如出现乱码文件,实质可以在服务器的响应头层面去设置编码方式。如果返回的是一个html则可以从meta里去设置

延伸:ajax的请求头 VS nodejs的响应头
miya Wang:#hello,JS:12-01技术方案:Ajax 使用和原理

  • ajax请求头:即服务器发送、返回时带的一些资源数据,如将url包含的一些各类数据作为请求资源,做一些加载、拼接等,然后返回结果数据。
  • nodejs的响应头:服务器对所请求的东西后台参数的一些响应,如设置页面展示效果的展示

4、加一个定时器观察服务器的响应

项目文件代码如下:

//项目文件:(新)index.js

var http = require('http')

var server = http.createServer(function(request, response){
  setTimeout(function(){
   
    response.setHeader('Content-Type','text/html; charset=utf-8')
//响应头:论及权限高,charset=utf-8作为请求http(浏览器)级别的请求,去解码
//发一个请求去响应:头、身体内容,根据头解释身体内容(一堆字符串)

    response.writeHead(404, 'Not Found')
    response.write('<html><head><meta charset="gbk" /></head>')
    response.write('<body>')
    response.write('<h1>你好</h1>')
    response.write('</body>')
    response.write('</html>')
    
    response.end()
  },2000);
})

console.log('open http://localhost:8080')
server.listen(8080)

重新启动终端:

$ node index.js

检查——控制台

延伸:针对http对应的状态码作用

先看到几个效果:

当Status Code:200时,如图:

image

当Status Code:400时,如图:
image

页面打开了(页面出现:你好)请求是成功的,但是打开控制台显示请求为红色,且console出现报错:404(Not found)。一旦浏览器收到状态码为404,它则认为文件请求失败,但实际上它也是收到请求并返回数据的。

总结:所请求的状态码通过response.writeHead()写出,完全由你来决定其页面呈现的状态

(二)实例二:实现一个静态服务器

准备好打包好的项目文件夹(包含html(css样式/js交互/图片))——网站放置在远程服务器上——通过执行服务器的相关js文件(执行node
server.js)——运行服务器

那么,这个运行服务器的js文件到底是怎么实现访问页面?

分析项目文件step1中的文件关键js文件:server.js,代码如下:

//server.js

var http = require('http') //前面说了,创建http服务器的底层内置模块
var path = require('path')  //该模块可以处理不同系统下的url(不同系统路径写法不一)
var fs = require('fs')      //该模块读、写文件
var url = require('url')    //该模块自动解析url,读取信息,如控制台求location

function staticRoot(staticPath, req, res){
  console.log(staticPath)
  
  var pathObj = url.parse(req.url, true)
  console.log(pathObj)
  
  
  if(pathObj.pathname === '/'){
    pathObj.pathname += 'index.html'
  }

  var filePath = path.join(staticPath, pathObj.pathname)
  
  // var fileContent = fs.readFileSync(filePath,'binary')
  // res.write(fileContent, 'binary')
  // res.end()
  
  
  fs.readFile(filePath, 'binary', function(err, fileContent){
    if(err){
      console.log('404')
      res.writeHead(404, 'not found')
      res.end('<h1>404 Not Found</h1>')
    }else{
      console.log('ok')
      res.writeHead(200, 'OK')
      res.write(fileContent, 'binary')
      res.end()      
    }
  })
 
}

console.log(path.join(__dirname, 'static'))

var server = http.createServer(function(req, res){
  staticRoot(path.join(__dirname, 'static'), req, res)
})

server.listen(8080)
console.log('visit http://localhost:8080' )

当用户访问localhost:8080/index.html,如何让用户看到项目文件的内容呢?

实现的关键,分解来看:

var http = require('http') 
var path = require('path') 
var fs = require('fs')      
var url = require('url')    

var server = http.createServer(function(req, res){
  staticRoot(path.join(__dirname, 'static'), req, res)
})

server.listen(8080)
console.log('visit http://localhost:8080' )

通过 http.creatServer创建一个server,listen去启动一个服务器,监听8080端口,请求到来之后,进入server这个函数里,处理这个请求

写一个函数staticRoot()作为静态文件路径,将路径名、req、res都传递进去,如:

 staticRoot(path.join(__dirname, 'static'), req, res)

__dirname 为nodejs的内置变量,代表当前的文件server.js 再加上【static】,那么,path.join(__dirname, 'static') 则会生成一个 绝对路径
然后通过下面代码运行测试:

function staticRoot(staticPath, req, res){
  console.log(staticPath)
}

控制台随即得到项目文件的相关文件信息,通过绝对路径能读取文件
获取路径之后进行操作,
需要通过用户的url,给用户返回一些特定内容,发出请求得到返回的是console.log(req.url),req.url所返回的均是项目文件中的相关文件,即请求的均是这些文件index.html、a.css、logo.png,并得到,得到之后进行解析,如何解析?代码如下:

  var pathObj = url.parse(req.url, true)
  console.log(pathObj)

实现一个默认页面:设置一个默认路径:localhost:8080/index.html ,如何实现?代码如下:

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

发现原来可以这样设置一个默认路径的页面,也是很兴奋哦~:


image

通过一个parseName 去得到一个完整路径,即静态目录路径则进入打包项目文件夹里,那么加上 pathObj.pathname 就得到该项目文件所请求的绝对路径地址 filePath,代码如下:

  var filePath = path.join(staticPath, pathObj.pathname)

如何读取文件?代码如下

第1种:直接法

  var fileContent = fs.readFileSync(filePath,'binary')
  res.write(fileContent, 'binary')
  res.end()

第2种:异步(也可作为当做制作404的页面状态)

fs.readFile(filePath, 'binary', function(err, fileContent){
    if(err){
      console.log('404')
      res.writeHead(404, 'not found')
      res.end('<h1>404 Not Found</h1>')
    }else{
      console.log('ok')
      res.writeHead(200, 'OK')
      res.write(fileContent, 'binary')
      res.end()      
    }
  })

?处理关于乱码的事情

(三)实例三:实现功能更复杂的静态服务器(使用nodejs服务器理由解析)

如url可获取任何数据,mock数据与前端交互
分析项目文件step2中的文件server-simple.js,代码如下:

var http = require('http')
var fs = require('fs')
var url = require('url')

http.createServer(function(req, res){

  var pathObj = url.parse(req.url, true)
  console.log(pathObj)

  switch (pathObj.pathname) {
    case '/getWeather': //请求对应天气
      var ret
      if(pathObj.query.city == 'beijing'){
        ret = {
          city: 'beijing',
          weather: '晴天'
        }
      }else{
        ret = {
          city: pathObj.query.city,
          weather: '不知道'
        }
      }
      res.end(JSON.stringify(ret))
      break;
    case '/user/123':  //对应的路由
      res.end( fs.readFileSync(__dirname + '/static/user.tpl' ))
      break;
    default:
      res.end( fs.readFileSync(__dirname + '/static' + pathObj.pathname) )
  }
}).listen(8080)

先分解简单代码:

var http = require('http')
var fs = require('fs')

//根据函数req.url进行语句操作,假设req.url是请求getWeather,
//res.end()括号内则是请求后所要获取的结果。
http.createServer(function(req, res){
    switch (req.url){
        case '/getWeather':
          res.end(JSON.stringify({a:1,b:2}))
          break;
        case '/user/123':
          res.end( fs.readFileSync(__dirname + '/static/user'))
          break;
         default:
          res.end(  fs.readFileSync(__dirname + '/static'+req.url))
    }
}).listen(8080)

总结: 创建模块:http+fs模块——创建一个server——该server函数返回一个操作对象——该操作对象调用并启动端口为8080的服务器。当任何请求到来,只要以localhost:8080为前缀的url就会到达该服务器

终端启动:

$ node server-simple.js

刷新页面处理js文件中函数对象的请求,即

http.createServer(function(req, res){
    switch (req.url){
        case '/getWeather':
          res.end(JSON.stringify({a:1,b:2}))
          break;
        case '/user/123':
          res.end( fs.readFileSync(__dirname + '/static/user'))
          break;
         default:  //表示用户希望请求的是一个静态文件,直接从static文件夹中读取文件req.url
          res.end(  fs.readFileSync(__dirname + '/static'+req.url))
    }
}).listen(8080)

当我们访问static下的html、css、图片或者直接调取请求模块,都能获取相应的内容

一个复杂网站,具有静态功能,提供静态文件;可以处理动态路由;可以mock数据,通过以下代码启示:

var http = require('http')
http.createServer(function(req, res){
    switch (req.url){
        case '/getWeather':
          res.end(JSON.stringify({a:1,b:2}))
          break;
    }
}).listen(8080)

可以写一个ajax:

//b.js

var xhr = new XMLHttpRequest()
xhr.open('GET', '/getWeather?city=hangzhou', true)
xhr.send()
xhr.onload = function(){
  console.log(JSON.parse(xhr.responseText))
}

待续...

看nodejs这一节最后的时候,不知道是有点困逻辑无法梳理,还有一点复杂服务器的实现暂时看得不是很懂😂。并且对于nodejs的一些理论基础知识也是相对空白,看了阿里出品的《七天学会NodeJS》才发现原来老师是将理论融进这短短的几节课,然后就理解了很多理论的知识。

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

推荐阅读更多精彩内容