目录

  1. 1. 前言
  2. 2. 基础
    1. 2.1. 简介
    2. 2.2. require 指令
    3. 2.3. 创建服务器
  3. 3. 模块
  4. 4. 路由
  5. 5. 全局对象
    1. 5.1. __filename
    2. 5.2. __dirname
  6. 6. GET/POST请求
    1. 6.1. GET
    2. 6.2. POST
  7. 7. Web模块
    1. 7.1. 创建web服务器
    2. 7.2. 创建web客户端

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

Nodejs基础

2023/6/26 Basic Nodejs
  |     |   总文章阅读量:

前言

尽量从ctf角度出发来快速上手

菜鸟教程

官方文档:https://nodejs.cn/api/

基础

简介

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”

image-20230628181540532


模块

类似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(); 

运行得到

image-20230629120559553


路由

和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);

访问并传入参数查看结果

image-20230629121441799

获取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);

image-20230629123522810


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);

image-20230629124641643

image-20230629124655183


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

image-20230629125510769

创建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

image-20230629125804628