Node.js | 搭建后端服务器(含内置模块 http | url | querystring 的使用)
Posted 海底烧烤店ai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js | 搭建后端服务器(含内置模块 http | url | querystring 的使用)相关的知识,希望对你有一定的参考价值。
🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 蓝桥杯真题解析:蓝桥杯Web国赛真题解析
🧧 加入社区领红包:海底烧烤店ai(从前端到全栈)
🧑💼个人简介:即将大三的学生,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站,真的超级好用🍬
文章目录
前言
最近博主一直在牛客网刷题巩固基础知识,快来和我一起冲关升级吧!点击进入牛客网
这一节我们去学习NodeJs
的内置模块:http
、url
、querystring
,并使用它们来搭建我们的node
后端服务器,正式迈入后端开发!
这篇文章内容比较多,篇幅较长,建议先收藏再观看🍬
一、创建服务器
http
是node
的内置模块,我们可以直接引入它进行使用,http
这个模块内有一个createServer
方法,这个方法可以帮助我们快速创建一个服务器:
// 引入http模块
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// req:接受浏览器传的参数
// res:返回渲染的内容
).listen(3000, () => // 服务器端口号为3000
console.log("服务器启动啦!");
);
另一种写法(推荐写法):
const http = require("http");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
// req:接受浏览器传的参数
// res:返回渲染的内容
);
server.listen(3000,() => // 服务器端口号为3000
console.log("服务器启动啦!");
);
createServer
方法返回一个服务器对象,对象内有一个listen
方法,可以设置服务器启动的端口号和启动成功的回调内容
通过nodemon
运行这个文件(nodemon
可以在我们修改文件后帮助我们自动重启服务器),控制台打印出了我们在listen
中设置的回调内容,说明服务器启动成功了
我们直接在浏览器访问http://localhost:3000/
时会发现浏览器一直在转圈圈加载
注意: 直接在浏览器地址栏里访问服务器接口,相当于是使用
get请求
访问服务器接口(并且没有跨域限制)
这是因为我们并没有在我们创建的node
服务器中返回任何内容
二、返回响应数据
我们可以通过我们定义的res
(response
对象)参数向客户端发送响应内容:
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// req:接受浏览器传的参数
// res:返回渲染的内容
// 传递数据
res.write("hello world");
res.write("Ailjx");
res.end();
).listen(3000, () =>
console.log("服务器启动啦!");
);
write
方法传递内容,可以调用多次write
传递多条内容,内容必须是字符串格式- 最后必须调用
end
方法告诉请求的调用者我们响应结束了 - 也可以直接在
end
方法内传递内容,效果与使用write
方法相同,但end
方法只能调用一次
运行上述代码,我们直接在浏览器调用服务器接口:
如果服务器中不调用end
方法,浏览器会收不到服务器传递的响应结束的信号,便会一直加载请求:
返回复杂对象数据
可以传递复杂对象数据,但必须是字符串(JSON
)的格式:
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// end方法也可以传递内容,效果与write相同
res.end("name:me:'Ailjx'");
// 或者res.end(JSON.stringify( name: me: "Ailjx" ));
).listen(3000, () =>
console.log("服务器启动啦!");
);
上面浏览器显示的数据被格式化了,是因为我在浏览器中安装了FeHelper(前端助手)插件,能够自动格式化JSON数据,点击查看博主推荐的浏览器插件
返回html文档数据
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// 传递html内容
res.end(`
<h1>我是Ailjx,你好!</h1>
`);
).listen(3000, () =>
console.log("服务器启动啦!");
);
这时发现我们传递的中文乱码了,我们可以在响应头的Content-Type
中指定utf-8
的字符集来解析中文,下面会讲到
三、设置响应头和状态码
我们可以使用response
对象的writeHead
方法来同时设置状态码和响应头信息:
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// 设置相应头,第一参数为状态码,第二个参数为响应头配置,第二个参数可不填
res.writeHead(200, "Content-Type": "text/html;charset=utf-8" );
// 传递html内容
res.end(`
<h1>我是Ailjx,你好!</h1>
`); // 直接在end中传递,效果与write方法相同
).listen(3000, () =>
console.log("服务器启动啦!");
);
我们也可以使用setHeader
单独设置响应头信息,statusCode
单独设置状态码:
const http = require("http");
// 创建服务器
http.createServer((req, res) =>
// 设置相应头信息
res.setHeader("Content-Type", "text/html;charset=utf-8");
// 设置状态码
res.statusCode = 200;
// 传递html内容
res.end(`
<h1>我是Ailjx,你好!</h1>
`); // 直接在end中传递,效果与write方法相同
).listen(3000, () =>
console.log("服务器启动啦!");
);
四、实现路由接口
上面我们已经成功创建了一个服务器,并能够使用res
参数中的write
或end
方法向调用者发送内容,但发送的这些内容是不会随着我们请求的路径而变化的:
const http = require("http");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
res.end("Ailjx");
);
server.listen(3000);
可以看到,我们请求(访问)不同路径,服务器返回的数据都是一样的,而我们在实际开发中往往是需要不同的路径有不同的数据
这时我们就可以利用我们创建服务器时定义的req
参数(request
对象)来获取用户请求的路径从而判断需要返回哪些数据:
const http = require("http");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
// req.url拿到用户请求的路径
console.log(req.url);
res.end();
);
server.listen(3000);
运行代码,之后在浏览器访问调用一下http://localhost:3000/list,控制台会打印出:
可以看到我们访问的/list
路径确实被打印出来了,但怎么还打印了一个/favicon.ico
呢?
这其实是浏览器在访问一个域名时会自动访问该域名下的/favicon.ico
静态文件,来作为网页标签栏的小图标,所以我们的服务器才会打印出/favicon.ico
如果是普通的ajax
调用接口是不会出现这种情况的,这里我们是为了方便,直接使用浏览器访问接口来进行演示,所以才出现这种请求,我们可以简单做一下处理:
const http = require("http");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
// req.url获取用户请求的路径
if (req.url === "/favicon.ico")
// 读取本地图标
return;
console.log(req.url);
res.end("Ailjx");
);
server.listen(3000);
这样当服务器收到/favicon.ico
请求时就能直接跳过不对其进行处理
创建简易路由应用
现在,我们开始实现一个简易的路由应用,我们先创建两个模块:
renderContent.js
用来根据用户请求路径来返回对应的内容:
function renderContent(url)
switch (url)
case "/api/home":
return `
page:'首页'
`;
case "/api/about":
return `
page:'关于页'
`;
default:
return "404";
exports.renderContent = renderContent;
renderStatus.js
用来根据用户请求的路径来返回对应的响应状态码:
function renderStatus(url)
const arr = ["/api/home", "/api/about"];
return arr.includes(url) ? 200 : 404;
module.exports =
renderStatus,
;
之后在我们的服务器文件server.js
中调用这两个模块:
const http = require("http");
const renderContent = require("./module/renderContent");
const renderStatus = require("./module/renderStatus");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
// req.url获取用户请求的路径
if (req.url === "/favicon.ico")
return;
// 响应头
res.writeHead(renderStatus(req.url),
// 标志返回JSON数据
"Content-Type": "application/json",
);
// 返回的内容
res.end(renderContent(req.url));
);
server.listen(3000);
之后启动服务器,在浏览器调用接口查看效果:
五、处理URL
在上面我们通过判断req.url
来实现了简易的路由接口应用,但当用户调用带有url参数的接口时,这就会出现问题:
这是因为这时req.url
为/api/about?name=ailj
而并不是/api/about
,我们可以手动的对这个字符串进行处理来获得正确的路由路径,也可以使用node.js
的内置模块url
来处理
URL格式转换
修改上面的server.js
文件:
const http = require("http");
const url = require("url");
const renderContent = require("./module/renderContent");
const renderStatus = require("./module/renderStatus");
// 创建服务器
const server = http.createServer();
server.on("request", (req, res) =>
// req.url获取用户请求的路径
if (req.url === "/favicon.ico")
return;
// 新版使用全局的URL构造函数
// 传两个参数用法
const myUrl = new URL(req.url, "http://127.0.0.1:3000").pathname;
// 传一个参数用法
// const myUrl = new URL("http://127.0.0.1:3000" + req.url).pathname;
console.log(new URL(req.url, "http://127.0.0.1:3000"));
res.writeHead(renderStatus(myUrl),
"Content-Type": "application/json",
);
res.end(renderContent(myUrl));
);
server.listen(3000, () =>
// 服务器端口号为3000
console.log("服务器启动啦!");
);
全局的构造函数UR可以将完整的 url
地址转换成url
对象(WHATWG URL标准的对象)
我们可以对其传递两个参数,第一个是用户请求的路径(路由),第二个参数是地址的根域名(我们这里是本地启动的服务器,根域名为
http://127.0.0.1:3000
)
也可以直接传递一个参数,该参数是带有域名的完整
url
地址
当我们访问http://localhost:3000/api/about?name=ailjx
时server.js
会打印出:
URL
href: 'http://127.0.0.1:3000/api/about?name=ailjx',
origin: 'http://127.0.0.1:3000',
protocol: 'http:',
username: '',
password: '',
host: '127.0.0.1:3000',
hostname: '127.0.0.1',
port: '3000',
pathname: '/api/about',
search: '?name=ailjx',
searchParams: URLSearchParams 'name' => 'ailjx' ,
hash: ''
上面Url
对象里 searchParams
是url
的参数部分,是一个迭代器对象(URLSearchParams对象):
// searchParams对象是一个迭代器对象
const query = new URL(req.url, "http://127.0.0.1:3000").searchParams;
// 使用get方法获取指定的值
console.log(query.get("name")); // ailjx
我们还可以从组成部分构造 URL
并获取构造的字符串:
const myURL = new URL("https://www.baidu.com");
myURL.port = "443";
myURL.pathname = "/ad/index.html";
myURL.search = "?id=8&name=mouse";
myURL.hash = "#tag=110";
// 获取构造的 URL 字符串,请使用href属性访问器
console.log(myURL.href); // https://www.baidu.com/ad/index.html?id=8&name=mouse#tag=110
或者:
const pathname = '/a/b/c';
const search = '?d=e';
const hash = '#fgh';
const myURL = new URL(`https://example.org$pathname$search$hash`);
console.log(myURL.href);
使用url.format
方法可以自定义序列化url
字符串,format方法接收两个参数:
new URL
返回的一个WHATWG URL
格式的对象- 配置对象:
fragment
:序列化的网址字符串是否包含片段,默认为true
auth
:序列化的网址字符串是否包含用户名和密码,默认为true
unicode
:是否将出现在URL
字符串的主机组件中的Unicode
字符直接编码而不是Punycode
编码,默认是false
search
:序列化的网址字符串是否包含搜索查询(参数),默认为true
const myURL = new URL(
"https://username:password@URL路径序列化测试?name=ailjx#foo"
);
console.log(
url.format(myURL,
fragment: false, // 不显示片段(#foo)
unicode: true, // 不转化Unicode字符(中文字符)
auth: false, // 不包含用户名和密码(username:password)
search: false, // 不显示参数(?name=ailjx)
)
);
// 打印结果: 'https://url路径序列化测试/'
-
旧版Node使用parse和format处理URL:
注意:旧版的
parse
方法官方表示已弃用,format
方法在新版中使用方式有所更改const http = require("http"); const url = require("url"); const renderContent = require("./module/renderContent"); const renderStatus = require("./module/renderStatus"); // 创建服务器 const server = http.createServer(); server.on("request", (req, res) => // req.url获取用户请求的路径 if (req.url === "/favicon.ico") return; console.log(url.parse(req.url)); const myUrl = url.parse(req.url).pathname; res.writeHead(renderStatus(myUrl), "Content-Type": "application/json", ); res.end(renderContent(myUrl)); node基础1--初识Node.js与内置模块
青训营Node.js基础 - Web应用开发 - 开发调试 - 线上部署
青训营Node.js基础 - Web应用开发 - 开发调试 - 线上部署