NodeJS处理HTTP响应与请求


@


一、系统模块http -- 创建web服务端

http 模块 是 Node.js 官方提供的、用来 创建 web 服务器 的模块。

不需要使用 IIS、Apache 等这些第三方 web 服务器软件,可直接通过 http 模块提供的 http.createServer() 方法,就能方便的把一台普通的电脑,变成一台最基本的 Web 服务器,从而对外提供 Web 资源服务。

//app.js
// 1. 引用http系统模块
const http = require('http');

// 2. http.createSercer(): 创建web服务器
const server = http.createServer();

// 3. 为服务器实例绑定 request 事件
server.on('request', (req, res) => {
	console.log('someone visit my web server')
})

// 4. 启动服务器
// Server.listen(端口号, callback):监听端口,网站服务器必须监听端口,否者无法向外服务
server.listen(3000, () => {
	console.log('服务器已启动,监听3000端口,请访问 localhost:3000')
});

之后通过命令行的方式开启服务器端node app.js


二、NodeJS服务端接收并处理客户端请求

server.on('requeset', function(req, res){})

在服务器创建成功后,调用通过 on() 为服务器注册的 request 事件 并绑定处理函数,函数中可传入两个参数

其中参数 req表示 客户端请求相关的数据或属性

另一个参数 res 表示 服务器响应相关的数据或属性

举例:

// 通过 on 方式 添加 请求事件 request, 后面函数为事件绑定函数, 当客户端发送请求到服务端就执行该函数;
/*
req : 代表请求对象,该对象保存了请求相关的信息
res : 代表响应对象, 对客户端的请求进行响应
*/
server.on('request', (req, res) => {

	//req.method : 获取请求方式
	console.log(req.method);
	
	//req.url : 获取请求地址
	console.log(req.url);
	
	//req.headers : 获取请求报文
	console.log(req.headers);

	/* 
	res.writedHead(parms1, parms2): 设置响应报文
		parms1: 设置响应头中的 http状态码, Number
		parms2: 设置响应头中的头部字段, object
	注意:res.writedHead() 需要在 res.end() 之前调用才有效
	*/ 
	res.writeHead(200, {
		//指定响应头中Content-Type字段值,值为响应内容类型,指定字符编码以免乱码
		'Content-Type': 'text/html;charset=utf8'
	});
	
	//res.end() : 根据请求响应客户端
	res.end('这是服务端响应给客户端页面的内容');
});

在这里插入图片描述


③ 解决中文乱码问题

当调用 res.end() 方法,向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式:

server.on('request', (req, res) => {
	// 响应内容包含中文
	const str = `您的请求的 url 地址是 ${req.url}, 请求的 method 类型是  ${req.method}`;
	// 为了防止显示中文乱码问题,需要设置响应头 Content-Type 的值为 text/html; charset=utf-8
	res.setHeader('Content-Type', 'text/html; charset=utf-8')
	// 把包含中文的内容,响应给客户端
	res.end(str)
})

三、NodeJS 服务端处理请求参数

1. 系统模块url -- 处理GET请求参数

get请求参数一般放置在浏览器地址栏中,例如:http://localhost:3000/?name=zhangsan&age=20

  • 参数获取需要借助系统模块url,url模块用来处理url地址
  • 通过 url.parse() 来解析req.url地址,并更具第二参数判断是否以对象的方式饭返回
//eg :在服务端接收到客户端请求中的参数
const http = require('http');
// 导入url系统模块 用于处理url地址
const url = require('url');
const app = http.createServer();
app.on('request', (req, res) => {
	console.log(req.url);
	console.log(url.parse(req.url, true));
	// 将url路径的各个部分解析出来并返回对象
	// true 代表将参数解析为对象格式
	let {query, pathname} = url.parse(req.url, true);
		console.log(query);
		console.log(pathname)
	});
app.listen(1234);

在这里插入图片描述



2. 系统模块querystring -- 处理POST请求参数

  • 参数被放置在请求头中发送到服务端
    在这里插入图片描述

  • 使用 querystring系统模块 将post参数转换为 对象格式

  • 获取POST参数需要使用 data事件和 end事件

如果post参数数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以 data 事件可能会触发多次,每一次触发 data 事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接;
当请求体数据接收完毕之后,会自动触发 req 的 end 事件。

// 导入系统模块querystring 用于将HTTP参数转换为对象格式
const querystring = require('querystring');
app.on('request', (req, res) => {
	//拼接post请求参数
	let postData = '';
	
	// post参数是通过事件的方式接受的
	// 监听参数传输事件, 当请求参数传递的时候出发data事件, params: post请求传输的数据
	req.on('data', (params) => {
		console.log(params)
		postData += params
	});
	// 监听参数传输完毕事件, 当参数传递完成的时候出发end事件
	req.on('end', () => {
		// 通过querystring模块的parse方法解析 字符串参数postData 成对象格式并返回
		console.log(postData )
		console.log(querystring.parse(postData))
	});
});

在这里插入图片描述


四、NodeJS服务端实现路由

1. 原生实现路由

路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么,动态响应内容:
在这里插入图片描述
路由实现代码

// 当客户端发来请求的时候
app.on('request', (req, res) => {
	// 获取客户端的请求路径
	let { pathname } = url.parse(req.url);
	res.setHeader('Content-Type', 'text/html; charset=utf-8')
	
	if (pathname == '/' || pathname == '/index') {
		res.end('欢迎来到首页');
	} else if (pathname == '/list') {
		res.end('欢迎来到列表页页');
	} else {
		res.end('抱歉, 您访问的页面出游了');
	}
});

简单案例:

const http = require('http');
const url = require('url');
const app = http.createServer();
const querystring = require("querystring");

app.on('request', (req, res) => {
    let method = req.method.toLowerCase();
    let path = url.parse(req.url);
    let postparms = '';

    res.writeHead(200, {
        'Content-Type': 'text/html;charset=utf8'
    })

    if (method == "get") {
        switch (path.pathname) {
            case '/':
            case '/index':
                res.end('<h2>欢迎来到首页<h2>');
                break;
            case '/list':
                res.end('<h2>欢迎来到列表页<h2>');
                break;
            case '/login':
                res.end(`<h2>欢迎来到登录界面</h2>
                <form method="POST" action="http://localhost:1234/success">
                    <input type="text" name="username">
                    <input type="password" name="password">
                    <input type="submit">
                </form>
                `);
                break;

            default:
                res.end('<h2 style="color: red">您访问的页面不存在!<h2>');
        }
    } else if (method == "post") {

        req.on('data', (parms) => {
            postparms += parms;
        })
        req.on('end', () => {
            postparms = querystring.parse(postparms);
            let username = postparms.username;
            let password = postparms.password;
            switch (path.pathname) {
                case '/success':
                    res.end("登录成功!<br>您的用户名为:" + username + "<br>您的密码为" + password);
            }
        })

    }
})

app.listen(1234);
console.log('服务器已启动,监听1234端口,请访问 localhost:1234');

2. 第三方模块 router

router - npm (npmjs.com)

功能:实现路由

使用步骤:

  1. 获取路由对象
  2. 调用路由对象提供的方法创建路由
  3. 启用路由,使路由生效
//引入router第三方模块并返回一个函数
const getRouter = require('router')
//通过调用getRouter()获取路由对象router, 实际也是函数
const router = getRouter();
/*路由对象.get(参数1, 参数2)
功能:用来接收get请求
参数1:Url请求地址
参数2:当前请求处理函数, 
	req: 请求对象
	res: 响应对象
*/
router.get('/add', (req, res) => {
res.end('Hello World!')
})

/*路由对象.post()
功能:用来接收post请求
参数:与get()一样
*/
router.post('/',(req, res) => {
    res.end();
})

/*
server: 由http模块创建的服务器对象
通过给服务器对象添加请求事件捕获请求并开启路由功能
*/
server.on('request', (req, res) => {
    /*
    通过调用router()启用路由功能,    
    router函数根据请求类型和请求地址自动匹配get()或post()
    参数说明:
    req:请求对象
    res:响应对象
    callback:当请求结束后会自动调用这个回调函数,它是必填参数
    */
	router(req, res, () => {})
    
})



五、NodeJS服务端响应静态资源

服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。

① 第三方模块 mime

mime - npm

转载文章

app.on('request', (req, res) => {
	// 获取用户的请求路径
	let pathname = url.parse(req.url).pathname;

	pathname = pathname == '/' ? '/default.html' : pathname;

	// 将用户的请求路径转换为实际的服务器硬盘路径, join方法可自动生成路径链接符
	let realPath = path.join(__dirname, 'public' + pathname);

	//识别当前请求文件的文件类型
	let type = mime.getType(realPath)

	// 读取文件
	fs.readFile(realPath, (error, result) => {
		// 如果文件读取失败
		if (error != null) {
			res.writeHead(404, {
				'content-type': 'text/html;charset=utf8'
			})
			res.end('文件读取失败');
			return;
		}
		res.writeHead(200, {
			//根据类型,指定当前请求响应报文中的content-type,便于浏览器正确读取文件格式
			'content-type': type
		})
		res.end(result);
	});
});

② 第三方模块 serve-static

serve-static - npm (npmjs.com)

功能:实现静态资源访问服务
步骤:

  1. 引入serve-static模块获取创建静态资源服务功能的方法
  2. 调用方法创建静态资源服务并指定静态资源服务目录
  3. 启用静态资源服务功能
//导入第三方模块'serve-static' , 并返回了一个方法
const serveStatic = require('serve-static')
/*调用返回的方法: serveStatic(参数1)
功能:实现静态资源访问服务功能
参数1:静态资源文件目录(绝对路径)
返回值:一个方法
*/
const serve = serveStatic('public')
//server: 由http模块创建的服务器对象
server.on('request', () => {
	/*
	启用静态资源服务
    方法实现过程:根据请求对象来判断当前请求是否访问静态资源,如果是静态资源,它会把静态资源直接响应给客户端
    callback: 请求结束后会自动调用回调函数,必填参数
    */
    serve(req, res, callback);
})
server.listen(3000)


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM