资讯专栏INFORMATION COLUMN

Node的Web开发

zengdongbao / 1673人阅读

摘要:中可以利用模块进行服务器的搭建。每个响应都必须调用方法,并且在最后调用。中后面的部分叫做。方法封装了和方法常识模块的服务器默认返回的数据类型是模块中的属性包含所有的状态码及其描述信息

使用Node进行网络开发

用户在浏览器中输入网址 --> 获得网页的过程经历了几个步骤:

通过浏览器发送一个请求到服务器(期间经历的DNS解析、TCP3次握手连接)

服务器分析、处理用户的请求,并生产请求的内容,然后发送给浏览器

浏览器解析服务发送回的数据,生产网页

服务器

在HTTP协议中的服务器指:监听客户端的请求,并且根据请求的内容进行相应处理,返回响应给客户端。

Node中可以利用http模块进行Web服务器的搭建。

http模块

http模块不是Node的核心模块,需要利用require()加载

使用http.createServer()方法创建一个http服务器,返回一个http服务器对象

利用服务器对象进行开发

接收的回调函数是监听到客户端请求时的回调函数

server.listen()方法可以开启Web服务,监听某台主机的某个端口

参数是(port, hostname, backlog, callback)

port是监听主机的端口号;hostname是监听主机的IP地址;callback是服务器成功开启后的回调函数(开启服务器后,再连接数据库

// 搭建一个HTTP服务器,用于处理用户发送的http请求
// http模块不是核心模块,需要require()导入
var http = require("http");

// http模块的createServer()方法可以返回一个标准http服务器对象
// 通过服务器对象来进行开发
// callback是监听到客户端连接的回调函数
var server = http.createServer(callback);

// 服务器监听某个网卡上的某个端口,开启服务
// listen(port, hostname, backlog, callback)
// port是监听的端口,hostname是监听主机的ip地址,callback是服务器开启成功后的回调函数

// 服务器开启失败时触发error事件
server.on("error", function (err) {
  console.log(err);
})

// listening事件在服务器开启成功时触发
server.on("listening", function () {
  console.log("listening...8080");
})

// 监听来自客户端的请求事件,在接收到请求时触发
server.on("request", function () {
  console.log("there is a request");
})

server.listen(8080, "localhost");

主要的事件

服务器开启失败的事件error的监听:server.on("errro", function(err) {})

服务器开启成功的事件listening的监听:server.on("listening", function(err) {})可以写在server.listen()方法的回调函数中

服务器接收到请求的事件request的监听:server.on("request", function(err, req, res) {})可以写在http.createServer()方法的回调函数中

参数对象

request事件接收两个参数:

request对象:提供客户端请求相关数据的对象,是http.IncomingMessage类的一个实例,有对应的属性与方法

httpVersion属性:使用的HTTP协议版本

header属性:请求头中相关的数据

url属性:

method属性:请求的方式

...

response对象:服务端向客户端发送的响应数据对象,是http.ServerResponse类的一个实例

write(chunk, [encoding]):发送一个数据库到响应的正文(网页的内容数据)中,需要在发送完成后调用res.end()方法

end(chunk, [encoding], [callback]):在通过write()方法发送完所有正文和头信息后,需要res.end()告诉服务器数据全部发送完成。每个响应都必须调用res.end()方法,并且在最后调用
如果指定了 chunk,则它等同于调用 response.write(chunk, encoding) 之后调用 response.end(callback)

writeHeader(statusCode [, statusMessage] [, headers]):写入头信息,res.write()前调用,并且一次响应中只能调用一次,头信息写在一个对象中

statusCode属性和setHeader()方法可以组合实现writeHeader()的功能

server.on("request", function (req, res) {
console.log("there is a request");
var chunk = "

hello world

"; // Buffer.byteLength(chunk)以字节为单位,告诉浏览器以纯文本解析传回的数据 res.writeHeader(200, "OK", {"Content-type": "text/plain", "Content-length": Buffer.byteLength(chunk)}); res.end(chunk, "utf-8"); })

url处理

根据用户请求的path返回不同的数据,使用req.url可以获取path信息。

req.url?后面的部分叫做query

Node下的url模块可以处理请求的中的req.url

使用switch结构,为不同的pathname划分不同的逻辑处理方式

server.on("request", function (req, res) {
console.log(req.url);   //  req.url获取请求的路径path信息
var urlStr = url.parse(req.url);
switch(urlStr.pathname) {
  case "/":  // 首页
res.writeHeader(200, "OK", {"Content-type": "text/plain"});
res.end("

首页

", "utf-8"); break; case "/users": // 用户页 res.writeHeader(200, "OK", {"Content-type": "text/plain"}); res.end("

用户页

", "utf-8"); break; default : // 不存在 res.writeHeader(404, "Not Found", {"Content-type": "text/plain"}); res.end("

出错

", "utf-8"); break; } })

使用fs模块实现行为与表现分离

根据用户不同访问的不同路径,执行不同操作,读取不同页面

server.on("request", function (req, res) {
  console.log(req.url);
  var urlStr = url.parse(req.url);

  switch(urlStr.pathname) {
    case "/":  // 首页
      sendData(htmlDir + "/index.html", req, res);  // 请求不同的路径,读取不同的页面返回给客户端
      break;

    case "/users":  // 用户页
      sendData(htmlDir + "/user.html", req, res);
      break;

    default :  // 不存在
      sendData(htmlDir + "/404.html", req, res);
      break;
  }
});

//  每次请求都读取静态页面,再输出。   fs.readFile()方法封装了fs.open()、fs.read()和fs.close()方法
// fs.readFile()返回值是原始的buffer对象
function sendData(file, req, res) {
  fs.readFile(file, function (err, data) {
    if(err) {
      res.writeHeader(404, "Not Found", {"Content-Type": "text/html"});
      res.end("Not Found");
    } else {
      res.writeHeader(200, "OK", {"Content-Type": "text/html"});
      res.end(data);
    }
  });
}
处理GETPOST请求提交的数据

通过GET方法传递的数据可以使用url.parse(req.url).query获取到GET请求提交的数据,使用querystring内置模块(无需加载)来解析

GET请求提交的数据绑定在url中,使用querystring.parse()方法解析urlquery属性便可以得到GET请求提交的数据

POST请求提交的数据在HTTP的Body中,服务器接收到的是数据流(因为POST请求提交的数据量较大,需要从缓冲区区读取chunk

利用request对象的data事件,触发回调函数接收所有提交的数据。可以将其拼接到一个字符串上

接收完所有数据后触发end事件,此时才可以使用querystring.parse()解析接收到的所有数据

var http = require("http");
var url = require("url");
var fs = require("fs");
var querystring = require("querystring");

var server = http.createServer();

var htmlDir = __dirname + "/html/";   // 使用fs读取html目录下的文件

server.on("request", function (req, res) {
  var urlStr = url.parse(req.url);
  switch(urlStr.pathname) {
    case "/":  // 首页
      sendData(htmlDir + "/index.html", req, res);
      break;

    case "/users":  // 用户页
      sendData(htmlDir + "/user.html", req, res);
      break;

    // 增加登录页面的路由
    case "/login":  // 用户页
      sendData(htmlDir + "/login.html", req, res);
      break;
    // 增加登录页面提交数据的处理
    case "/login/check":  // 用户页
      if(req.method.toUpperCase() === "GET") {
        console.log(querystring.parse(urlStr.query));    // 使用querystring.parse()将传递的数据解析为一个对象
      }
      if(req.method.toUpperCase() === "POST") {
        var str = "";   // 用来接收POST传递来的数据
        req.on("data", function (chunk) {
          str += chunk;
        })
        req.on("end", function () {
          console.log(querystring.parse(str));
        })
      }
      break;

    default :  // 不存在
      sendData(htmlDir + "/404.html", req, res);
      break;
  }
});

//  每次请求都读取静态页面,再输出。   fs.readFile()方法封装了fs.open()、fs.read()和fs.close()方法
function sendData(file, req, res) {
  fs.readFile(file, function (err, data) {
    if(err) {
      res.writeHeader(404, "Not Found", {"Content-Type": "text/html"});
      res.end("Not Found");
    } else {
      res.writeHeader(200, "OK", {"Content-Type": "text/html"});
      res.end(data);
    }
  });
}

server.listen(8080, "localhost");

常识

http模块的服务器默认返回的数据类型是text/html

http模块中的http.STATUS_CODES属性包含所有的状态码及其描述信息

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86900.html

相关文章

  • 【全文】狼叔:如何正确学习Node.js

    摘要:感谢大神的免费的计算机编程类中文书籍收录并推荐地址,以后在仓库里更新地址,声音版全文狼叔如何正确的学习简介现在,越来越多的科技公司和开发者开始使用开发各种应用。 说明 2017-12-14 我发了一篇文章《没用过Node.js,就别瞎逼逼》是因为有人在知乎上黑Node.js。那篇文章的反响还是相当不错的,甚至连著名的hax贺老都很认同,下班时读那篇文章,竟然坐车的还坐过站了。大家可以很...

    Edison 评论0 收藏0
  • 【全文】狼叔:如何正确学习Node.js

    摘要:感谢大神的免费的计算机编程类中文书籍收录并推荐地址,以后在仓库里更新地址,声音版全文狼叔如何正确的学习简介现在,越来越多的科技公司和开发者开始使用开发各种应用。 说明 2017-12-14 我发了一篇文章《没用过Node.js,就别瞎逼逼》是因为有人在知乎上黑Node.js。那篇文章的反响还是相当不错的,甚至连著名的hax贺老都很认同,下班时读那篇文章,竟然坐车的还坐过站了。大家可以很...

    fengxiuping 评论0 收藏0
  • 前端每周清单第 41 期 : Node 与 Rust、OpenCV 火花,网络安全二三事

    摘要:的网站仍然使用有漏洞库上周发布了开源社区安全现状报告,发现随着开源社区的日渐活跃,开源代码中包含的安全漏洞以及影响的范围也在不断扩大。与应用安全是流行的服务端框架,本文即是介绍如何使用以及其他的框架来增强应用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清单专注...

    syoya 评论0 收藏0
  • 精读《深入浅出Node.js》

    摘要:从社区和过往的经验而言异步编程的难题已经基本解决无论是通过事件还是通过模式或者流程控制库。本章主要介绍了主流的几种异步编程解决方案这是目前中主要使用的方案。最后因为人们总是习惯性地以线性的方式进行思考以致异步编程相对较为难以掌握。 前言 如果你想要深入学习Node,那你不能错过《深入浅出Node.js》这本书,它从不同的视角介绍了 Node 内在的特点和结构。由首章Node 介绍为索引...

    codergarden 评论0 收藏0
  • 几分钟阅读让你明白node.JS强大 走上web后端开发道路 (一版)

    摘要:这些特性不仅带来了大的性能提升,还减少多线程程序设计的复杂性,进而提高了开发效率。由公司建立的云计算平台率先支持了。 前言 本文章主要写给那些想了解node语言的开发,我的目标希望大家通过阅读本篇文章能够简单使用node进行开发,以及了解一些事件驱动的异步编程风格,主要分node的背景,安装配置,模块创建引用等几个方面描述 建议大家在阅读本篇文章途中 可以亲自尝试一下我所带来的小例子,...

    libxd 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<