前言
尽量从ctf角度出发来快速上手
基础
简介
node意为节点,直译过来就是节点js,通俗的来说Nodejs就是运行在服务端的js环境
之前写的JS全是在浏览器运行的,而Node.js可以让JS代码直接在服务器运行
和python一样,在终端输入node,可以进入交互界面
require 指令
在 Node.js 中,使用 require 指令来加载和引入模块,引入的模块可以是内置模块,也可以是第三方模块或自定义模块。类似于python中的import,引入文件名的.js可以省略
const module = require('module-name');
其中,module-name 可以是一个文件路径(相对或绝对路径),也可以是一个模块名称,如果是一个模块名称,Node.js 会自动从 node_modules 目录中查找该模块。
假设你引入一个模块a
,其中有方法b
,要调用方法b
,有如下方式
require('a').b
require('a')["b"]
载入http模块
var http = require("http");
一个模块中的变量和函数在其他js文件中无法访问,因为它不是全局作用域,相当于包裹在一个函数内,想要解决这个问题,我们得向外部暴露(export)属性:exports.x="test"
创建服务器
使用 http.createServer()
方法创建服务器,并使用 listen 方法绑定端口,通过 request
, response
参数来接收和响应数据
server.js文件
var http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
然后在终端使用node命令运行代码
node server.js
访问就能看到页面内容”Hello World”
模块
类似Java中的包,模块能让Node.js的文件可以相互调用
引入./hello模块
var Hello = require('./hello');
把对象封装到模块中
hello.js
function Hello() {
var name;
console.log("hello world");
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
然后在main.js中调用获得对象
var Hello = require('./hello');
hello = new Hello();
hello.setName('C1oudfL0w0');
hello.sayHello();
运行得到
路由
和python flask类似,nodejs框架也存在路由的说法
以下是一个简单示例:
server.js
var http = require("http");
var url = require("url");
function start() {
function onRequest(request, response) { // 当有请求到达时,会执行onRequest函数
var pathname = url.parse(request.url).pathname; // 通过url模块解析请求的URL路径
console.log("Request for " + pathname + " received."); // 在控制台输出接收到的请求的路径信息
route(pathname); // 将路由函数作为参数传递过去
response.writeHead(200, {"Content-Type": "text/plain"}); // 表示返回的内容为纯文本格式
response.write("Hello World"); // 向客户端发送"Hello World"的响应内容
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start; // 将start函数作为模块的一个属性进行导出
route.js
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
这段代码什么也没干
index.js
var server = require("./server");
var router = require("./router");
server.start(router.route); // 调用了server模块中的start函数,并传递了一个路由器函数作为参数
运行index.js以启动整个服务器
全局对象
在js里定义全局变量就不要在变量名前加var
即可
__filename
__filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是当前模块文件的路径。
// 输出全局变量 __filename 的值
console.log( __filename );
__dirname
__dirname 表示当前执行脚本所在的目录,即js文件所在文件夹的路径
GET/POST请求
GET
由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数。
node.js 中 url 模块中的 parse 函数提供了这个功能。
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(util.inspect(url.parse(req.url, true))); // 将请求的URL解析成一个JavaScript对象,并使用util模块的inspect方法将其转换为一个字符串,然后将该字符串作为响应返回给客户端
}).listen(3000);
访问并传入参数查看结果
获取url参数
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
// 解析 url 参数
var params = url.parse(req.url, true).query;
res.write("Name:" + params.name);
res.write("\n");
res.write("URL:" + params.url);
res.end();
}).listen(3000);
POST
POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。
比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所以 node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做。
基本结构:
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
实例POST.js:创建表单通过 POST 提交并输出数据
var http = require('http');
var querystring = require('querystring');
var postHTML =
'<html><head><meta charset="utf-8"><title>菜鸟教程 Node.js 实例</title></head>' +
'<body>' +
'<form method="post">' +
'网站名: <input name="name"><br>' +
'网站 URL: <input name="url"><br>' +
'<input type="submit">' +
'</form>' +
'</body></html>';
http.createServer(function (req, res) {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
// 解析参数
body = querystring.parse(body);
// 设置响应头部信息及编码
res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
if(body.name && body.url) { // 输出提交的数据
res.write("网站名:" + body.name);
res.write("<br>");
res.write("网站 URL:" + body.url);
} else { // 输出表单
res.write(postHTML);
}
res.end();
});
}).listen(3000);
Web模块
现在本地测试环境多使用express模块
npm install express
创建web服务器
web.js
var http = require('http');
var fs = require('fs');
var url = require('url');
// 创建服务器
http.createServer( function (request, response) {
// 解析请求,包括文件名
var pathname = url.parse(request.url).pathname;
// 输出请求的文件名
console.log("Request for " + pathname + " received.");
// 从文件系统中读取请求的文件内容
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP 状态码: 404 : NOT FOUND
// Content Type: text/html
response.writeHead(404, {'Content-Type': 'text/html'});
}else{
// HTTP 状态码: 200 : OK
// Content Type: text/html
response.writeHead(200, {'Content-Type': 'text/html'});
// 响应文件内容
response.write(data.toString());
}
// 发送响应数据
response.end();
});
}).listen(8080);
// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:8080/');
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试页面</title>
</head>
<body>
<h1>Hello</h1>
<p>world</p>
</body>
</html>
运行,访问http://127.0.0.1:8080/index.html
创建web客户端
client.js
var http = require('http');
// 用于请求的选项
var options = {
host: 'localhost',
port: '8080',
path: '/index.html'
};
// 处理响应的回调函数
var callback = function(response){
// 不断更新数据
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 数据接收完成
console.log(body);
});
}
// 向服务端发送请求
var req = http.request(options, callback);
req.end();
保持web.js运行的情况下在终端运行client.js