动态服务器

188 阅读1分钟
标题特征备注
静态网页未请求数据库
动态网页请求了数据库json代替数据库

动态服务器

// users.json
[  {"id"=1, "name":"frank", "password":"xxx"},  {"id"=2, "name":"jack", "password":"zzz"},]
// test.js
const fs = require("fs");
// 读数据库
const userString = fs.readFileSync("./db/users.json").toString();
const userArray = JSON.parse(userString);
// 写数据库
const user3 = {id:3, name:'tom', password:'yyy'}
usersArray.push(user3)
const string = JOSN.stringify(usersArray)
fs.writeFileSync("./db/users.json", string)

实现用户 注册 功能

用户提交用户名、密码,users.json里就新增一行数据

实现思路:

  • 前端写一个 form,让用户填写 namepassword
  • 前端监听submit事件
  • 前端发送 post 请求,数据位于请求体
  • 后端接收 post 请求
  • 后端获取请求体中的 namepassword
  • 后端存储数据
// users.json
[ ]
// signup.html 需引入jQuery库
<body>
   <form id="registerForm">
     <div>
       <label>用户名 <input type="text" name="name"></label>
     </div>
     <div>
       <label>密码 <input type="password" name="password"></label>
     </div>
     <div>
       <button type="submit">注册</button>
     </div>
   </form>
   <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
   <script>
     const $form = $('#registerForm')
     $form.on('submit', (e)=>{
       e.preventDefault()
       const name = $form.find('input[name=name]').val()
       const password = $form.find('input[name=password]').val()
       $.ajax({
         methods:'POST',
         url:'/register',
         contentType:'text/json; charset=UTF-8',
         data: JSON.stringify({name, password})
       })
     })
   </script>
</body>

获取 post 数据

if(path === "/register" && method === 'POST'){
  response.setHeader('Content-Type', 'text/html; charset=utf-8')
  const userArray = JSON.parse(fs.readFileSync('./db/users.json'))
  const array = []
  request.on('data', (chunk)=>{
    array.push(chunk)
  })
  request.on("end", ()=>{
    const string = Buffer.concat(array).toString()
    const obj = JSON.parse(string)
    const lastUser = userArray[userArray.length-1].id + 1}
    const newUser = {
      // id 为最后一个用户的 id + 1
      id: lastUser ? lastUser.id + 1 : 1,
      name: obj.name,
      password: obj.password
    };
    userArray.push(newUser)
    fs.writeFileSync('./db/users.json', JSON.stringify(userArray))
    response.end('fine');
  })
} else {}

此时填写用户名、密码后,点击注册,就会在数据库生成json数据:

[{"id":1, "name":"name111", "password":"mima"},{"id":2, "name":"name222", "password":"123"},]

用户注册成功后,跳转到登录页面:

// register.html
$.ajax({...}).then(()=>{
  alert('注册成功')
  location.href = '/sign_in.html'
},()=>{})

实现用户 登录 功能

  • 登录页sign_in.html,供提交用户名和密码
  • 首页 home.html,显示用户登录状态,然后已登录用户可看到自己用户名
  • 输入的用户名密码如果是匹配的,就自动跳转首页
// sign_in.html
<body>
   <form id="signInForm">
     <div>
       <label>用户名 <input type="text" name="name"></label>
     </div>
     <div>
       <label>密码 <input type="password" name="password"></label>
     </div>
     <div>
       <button type="submit">登录</button>
     </div>
   </form>
   <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
   <script>
     const $form = $('#signInForm')
     $form.on('submit', (e)=>{
       e.preventDefault()
       const name = $form.find('input[name=name]').val()
       const password = $form.find('input[name=password]').val()
       $.ajax({
         methods:'POST',
         url:'/sign_in',
         contentType:'text/json; charset=UTF-8',
         data: JSON.stringify({name, password})
       }).then(()=>{
         alert('登录成功')
         location.href = '/home.html'
       }, ()=>{})
     })
   </script>
</body>
// home.html
<p>
  {{loginStatus}}
</p>
<p>
  <a href="sign_in.html">登录</a>
</p>
// server.js
if(path === 'sign_in.html' && method === 'POST'){
  response.setHeader('Content-Type', 'text/html; charset=utf-8')
  const userArray = JSON.parse(fs.readFileSync('./db/users.json'))
  const array = []
  request.on('data', (chunk)=>{
    array.push(chunk)
  })
  request.on("end", ()=>{
    const string = Buffer.concat(array).toString()
    const obj = JSON.parse(string);
    const user = userArray.find((user)=> user.name === obj.name && user.password === obj.password)
    if(user === undefined){
      response.statusCode = 400;
      response.setHeader('Content-Type', 'text/json; charset=utf-8')
      response.end(`{"errorCode":4001}`);
    }else{
      response.statusCode = 200;
      // 服务器下发 cookie 识别登录状态,标记用户
      response.setHeader('Set-Cookie', ’logined=1‘)
      response.end();
    }   
  });
} else if(path === '/home.html'){
  const cookie = request.headers['cookie']
  if(cookie ==='logined=1'){
   const homeHtml = fs.readFileSync('./public/home.html').toString(); 
   const string = homeHtml.replace('{{loginStatus}}','已登录')
   response.write(string);
  }
  response.end('home');
} else

静态服务器

目的:自动查找对应文件,静态文件服务器。

  1. 新建一个static server文件夹,新建server.js文件作为服务端路由代码,新建public文件夹,存放index.html和style.css
if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(fs.readFileSync('./public/index.html'))
    response.end()
  } else if(path === '/style.css'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(fs.readFileSync('./public/style.css'))
    response.end()
  }
  1. 每次读取文件都要写代码,每一个文件对应一个if...else语句,需要实现在public下创建文件名为a.htmlb.htmlc.jsd.js这些文件,在地址栏直接敲a.html,就直接读取下面的文件,而不用添加那么多的if...else路由。

  2. 封装路径:

var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]
...
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
response.write(fs.readFileSync(`./public${x}`))
response.end()
  1. 若文件不存在,则添加新逻辑:
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
// 默认首页
const filePath = path === '/' ? '/index.html' : path
let content
try{
  content = fs.readFileSync(`./public${filePath}`)
}catch(error){
  content = '文件不存在'
  response.statusCode = 404
}
response.write(content)
response.end()
  1. 自动判断文件类型
response.statusCode = 200
const filePath = path === '/' ? '/index.html' : path
const index = filePath.lastIndexOf('.')
const suffix = filePath.substring(index)
// 用数据结构的方法判断文件类型
const fileTypes = {
  '.html':'text/html',
  '.css':'text/css',
  '.js':'text/javascript'
  '.png':'image/png',
  '.jpg':'image/jpeg'
}
response.setHeader('Content-Type', `$fileTypes[suffix] || 'text/html';charset=utf-8`)