# 服务端开发

# 服务器端基础概念

# 网站的组成

网站应用程序主要分为两大部分:客户端和服务器端。 客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用 HTML、CSS、JavaScript 构建。 服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。

# Node 网站服务器

能够提供网站访问服务的机器就是网站服务器,它能够接收客户端的请求,能够对请求做出响应。

# IP 地址

互联网中设备的唯一标识。 IP 是 Internet Protocol Address 的简写,代表互联网协议地址.

# 域名

由于 IP 地址难于记忆,所以产生了域名的概念,所谓域名就是平时上网所使用的网址。

http://www.itheima.com => http://124.165.219.100/

虽然在地址栏中输入的是网址, 但是最终还是会将域名转换为 ip 才能访问到指定的网站服务器。

# 端口

端口是计算机与外界通讯交流的出口,用来区分服务器电脑中提供的不同的服务。

# URL

统一资源定位符,又叫 URL(Uniform Resource Locator),是专为标识 Internet 网上资源位置而设的一种编址方式,我们平时所说的网页地址指的即是 URL。

# 创建 web 服务器

// 引入http模块
const http = require("http");
// 创建web服务器对象
const app = http.createServer();
// 当客户端发送请求的时候
app.on("request", (req, res) => {
  // 响应
  res.end("<h1>hi,user</hi>");
});
// 监听3000端口
app.listen(3000);
console.log("服务器已启动,监听3000端口,请访问\nlocalhost:3000");

# HTTP 协议

# HTTP 协议的概念

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。

# 报文

在 HTTP 请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式。

# 求报文

  1. 请求方式 (Request Method)

    • GET 请求数据
    • POST 发送数据

app.on("request", (req, res) => {
  if (req.method == "POST") {
    res.end("post");
  } else if (req.method == "GET") {
    res.end("get");
  }
});
  1. 请求地址 (Request URL)

app.on("request", (req, res) => {
  console.log(req.headers["accept"]); // 获取请求报文
  console.log(req.url); // 获取请求地址
});

# 响应报文

  1. HTTP 状态码
  2. 内容类型

app.on('request', (req, res) => {
    // 设置响应报文
    res.writeHead(200, {
        'Content-Type': 'text/html;charset=utf8‘
    });
    if (req.url == "/index" || req.url == "/") {
        res.end("<h2>欢迎来到首页</h2>");
    } else if (req.url == "/list") {
        res.end("welcome to listpage");
    } else {
        res.end("not found");
    }
});

# HTTP 请求与响应处理

# 请求参数

客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作。

# GET 请求参数

参数被放置在浏览器地址栏中,例如:http://localhost:3000/?name=zhangsan&age=20 参数获取需要借助系统模块 url,url 模块用来处理 url 地址

// 引入http模块
const http = require("http");
// 引入url模块——url模块专用解析方法url.parse()
const url = require("url");
// 创建web服务器对象
const app = http.createServer();
app.on("request", (req, res) => {
  // 请求参数
  console.log(req.url);
  // 解析查询参数{采用对象的解构赋值}
  let { query, pathname } = url.parse(req.url, true);
  console.log(query.name);
  console.log(query.age);
  console.log(pathname);
});
app.listen(3000);

# POST 请求参数

参数被放置在请求体中进行传输 获取 POST 参数需要使用 data 事件和 end 事件 使用 querystring 系统模块将字符串参数转换为对象格式

// 引入http模块
const http = require("http");
// 引入字符串处理模块
const querystring = require("querystring");
// 创建web服务器对象
const app = http.createServer();
app.on("request", (req, res) => {
  let postParams = "";
  //数据传输时
  req.on("data", (params) => {
    postParams += params;
  });
  //数据传完时
  req.on("end", () => {
    console.log(querystring.parse(postParams));
  });
  res.end("ok");
});

# 路由

路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。

// 当客户端发来请求的时候
app.on("request", (req, res) => {
  // 1.获取请求方式
  const method = req.method.toLowerCase();
  // 2.获取请求地址
  const { pathname } = url.parse(req.url);
  // 3.设置响应报文
  res.writeHead(200, {
    "content-type": "text/html;charset=utf-8"
  });
  // 根据请求方式和地址响应资源
  if (method == "get") {
    if (pathname == "/" || pathname == "/index") {
      res.end("欢迎来到首页");
    } else if (pathname == "/list") {
      res.end("欢迎来到列表");
    } else {
      res.end("您访问的页面不存在");
    }
  } else if (method == "post") {
    res.end("登录成功");
  }
});

# 静态资源

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

// 引入http模块
const http = require("http");
// 引入相关模块
const url = require("url");
const path = require("path");
const fs = require("fs");
const mime = require("mime");

// 创建web服务器对象
const app = http.createServer();
// 当客户端发送请求的时候
app.on("request", (req, res) => {
  // 1.获取用户的请求路径
  let { pathname } = url.parse(req.url);
  // 2.把默认参数/指向首页
  pathname = pathname == "/" ? "/default.html" : pathname;
  // 3.转换为资源所在的绝对路径
  let realPath = path.join(__dirname + "/public" + pathname);
  // 4.记录资源文件类型
  let type = mime.getType(realPath);
  // 5.调用fs模块读取文件,并返回静态资源
  fs.readFile(realPath, (error, result) => {
    // res.end(realPath);
    if (error != null) {
      res.writeHead(404, {
        "content-type": "text/html;charset=utf-8"
      });
      res.end("文件读取失败");
      return;
    }
    res.writeHead(200, {
      "content-type": type
    });
    res.end(result);
  });
});
// 监听3000端口
app.listen(3000);
// 提示服务已经开启
console.log("服务器已启动,监听3000端口,请访问localhost:3000");