记得用完服务器机器要关机(并选择停止计费)

记得用完服务器机器要关机(并选择停止计费)

记得用完服务器机器要关机(并选择停止计费)

记得用完服务器机器要关机(并选择停止计费)


前置条件

  • 安装Node.js 8+
  • 理解IP和端口
  • 理解URL路径和查询参数
  • 不需要会JavaScript
  • 本节所有代码建议复制使用

演示 Node.js Server

请求与响应模型

前端的代码在客户端Client(浏览器、APP)

IP 124.124.233.233:80

请求->服务器(Sever)

服务器(Sever)

IP 123.123.233.233:80

响应->客户端

如何发请求

方法

  • 用Chrome(地址栏输入URL)
  • curl命令

开发者工具Network面板,刷新页面

响应看Response,HTML CSS JS image等

概念

  • 帮你发送请求的工具叫「用户代理」
  • 即「User Agent」
  • 用Chrome时的用户代理就是Chrome
  • curl时的用户代理就是curl

如何模拟一个响应

curl

需用编程

  • Node.js有一个http模块可以做到
  • 使用以下初始代码

全部测试代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`二哈`)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

只要请求了8888端口,就会被server.js监听,每一次请求,就运行一遍此代码

注意事项

  • 这些代码就是服务器代码,一般放在服务器上
  • path是不带查询参数的路径/x
  • query是查询参数的对象形式{a:'1'}
  • queryString是查询参数的字符串形式?a=1
  • pathWithQuery是带查询参数的路径,一般不用
  • request是请求对象
  • response是响应对象

主要代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/******** 从这里开始看,上面不要看 ************/
  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`二哈`)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/

代码逻辑

语法

注意``,和''是不同的符号

  • ``,这种字符串里面可以回车
  • \’\‘,这种字符串要回车只能用\n表示
逻辑
  • 每次受到请求都会把中间的代码执行一遍
  • if else判断路径,并返回响应
  • 如果是已知路径,一律返回200
  • 如果是位置路径,一律返回400
  • Content-Type标示内容的「类型/语法」
  • response.write()可以填写返回的内容
  • response.end()表示响应可以发给用户了

nodejs-test

启动应用

node server.js 8888

或者

node server 8888

添加路由

  1. 编辑 server.js 文件,添加 if else
  2. 重新运行 node server.js 8888

后台启动应用

1
2
touch log
node server.js 8888 >log log 2>&1 &

curl访问8888,或者用浏览器

curl

1
2
node server.js 8888/x
curl http://127.0.0.1:8888

用浏览器

1
2
node server.js 8888
localhost:8888/x

查看终端的变化

遥想当年李爵士

Li写了世界上第一个服务器程序

  • 自己也完成了一个服务器程序,虽然代码是抄来的

Li写了世界上第一个网站

  • 自己在/路径返回一个HTML内容
  • 然后再/x路径返回一个CSS内容
  • 然后再/y路径返回一个JS内容

要记住的

1
2
3
4
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
response.write(`some CSS style code`)
response.end()

本质就是根据路径返回一个字符串或者文件

后缀是垃圾

  • URL里的后缀卵用没有,eg:/y.css不一定是CSS内容
  • Content-Type才是决定文件类型的关键

系统学习HTTP

HTTP到底是个啥

必须学会什么

  • 基础概念(必会知识):请求和响应
  • 如何调试(用的是Node.js,可以用log/debugger,但本质还是HTTP)
  • 在哪查资料(用的是Node.js,看Node.js文档)
  • 标准制定者(HTTP规格文档:RFC 2612等)

如何学

  • Copy 抄文档
  • Run 放在自己的机器上运行成功
  • Modify 加入一点自己的想法,然后重新运行

开发者工具

查看Network:分GeneralResponse Headers即请求、Request Headers即响应

HTTP基础概念:请求

请求的组成

  • 请求动词 + 路径查询参数 + 协议/版本(请求行)
  • Host:域名或IP及端口(请求头)
  • Accept:表示接受的内容格式,text/html(请求头)
  • Content-Type:请求体的格式(请求头)
  • 回车
  • 请求体(即放上传内容,可以是任意内容,但格式必须在请求头中写明)

测试查看

curl -v POST --data '上传内容' http://localhost:8888/

细节

  • 三部分:请求行、请求头、请求体
  • 请求动词有GET/POST/PUT/PATCH/DELETE
  • Get :获取;Post: 上传
  • /?wd=hi:路径及查询参数
  • HTTP/1.1协议及版本号
  • 请求体在GET中一般为空
  • 文档位于 RFC 2612第五章
  • 大小写不明感(随意,但涉及JS代码是大小写敏感的)

HTTP基础概念:响应

响应的组成

  • 协议名/版本 + 状态码 + 状态字符串(状态行)
  • Content-Type:响应体的格式text/html;charset=utf-8(响应头)
  • 回车
  • 响应体(即下载内容,可以在Response选项中查看具体内容)

细节

  • 三部分:状态行、响应头、响应体
  • 常见状态码(面试重点)
  • 文档位于 RFC 2612 第六章

要记住关于HTTP:请求和响应的规范写法

  • 请求的组成:请求行「请求动词 + 路径查询参数 + 协议/版本」+ 请求头「Host + Accept + Content-Type等」+ 请求体
  • 响应的组成:状态行「协议名/版本 + 状态码 + 状态字符串」+ 响应头「Content-Type等」+ 响应体
  • 常见状态码

用curl构造请求

回忆 curl 五行请求…

server.js开启的前提下:

curl -v http://127.0.0.1:8888

curl -v http://localhost:8888

  • -v:verbose,看过程
  • 注意不是https://

设置请求动词

  • -X POST
  • 注意大小写敏感
  • curl -v -X POST http://localhost:8888
  • curl -v -X POST http://localhost:8888/xxx?wd=hi加个查询
  • curl -v -X POST http://localhost:8888/xxx\?wd=hi加个查询,用Mac的终端
  • curl -v -X POST http://localhost:8888/xxx?wd=hi#nihao锚点不会发送到服务器
  • 看终端里返回的请求行

设置路径和查询参数

  • 直接在url后面加

设置请求头

  • -H 'Name:Value'或者--header 'Name:Value'
  • 单引号内必须是以键值对的形式

比如

curl -v -H 'Accept:text/html' http://localhost:8888/xxx\?wd=hi#nihao

设置请求体

  • -d '内容'或者--data '内容'

比如

curl -v -H 'Accept:text/html' -H 'FSociety:FyE' -H 'Content-Type:text/plain;charset:utf-8' -d '请求体的内容' http://localhost:8888/xxx\?wd=hi#nihao

  • 看终端里返回的请求行

用Node.js读取请求

读取请求动词

  • request.method

读取路径

  • request.url路径,带查询参数
  • path纯路径,不带查询参数
  • query只有查询参数

  • curl http://localhost:8888/\?hihihi=hohoho

  • 看终端里返回的请求行

读取请求头

  • request.headers['Accept']

  • curl -v -H 'Hi:nihao' http://localhost:8888/

  • 看终端里返回的请求行,可以得到所有符合格式的请求头

读取请求体

  • 比较复杂,待续~~~

用Node.js设置响应

设置响应状态码

  • response.statusCode = 200
  • response.statusCode = 201
  • response.statusCode = 299
  • response.statusCode = 300

设置响应头

  • response.setHeader('Content-Type','text/html')

设置响应体

  • response.write('内容')
  • 可追加内容

代码具体细节先不管,直接抄,运行看

  • 整个响应都可以有node来控制,包括响应状态码、响应头、响应体

404页面是什么

  • curl不仅可以用来测试,还可用来下载curl https://xxx.jpg > 1.jpg
  • curl可以完成Chrome除了显示界面外的几乎所有功能
  • 即使状态码为404,还是能接受到响应体,需要设置
  • 状态码和内容没有直接的关系,即不管状态码是什么,都可以是任何内容
  • 大部分服务器不设置404页面,不返回任何其他内容

如何调试JS

怎么知道自己写错了还是写对了

console.log调试大法

不要相信直觉,相信console.log

debug就是不断质疑自己的过程

不信,比如,只看,下面代码哪里有问题?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type','text/html;charset=utf-8')
    response.write(`
        <link rel="stylesheet" href="./style.css">
        <h1>你好</h1>
    `)
    response.end()
}else if(path === './style.css'){
    response.statusCode = 200
    response.setHeader('Content-Type','text/css;charset=utf-8')
    response.statusCode(`h1{color: red;}`)
    response.end()
}else{
    response.statusCode = 404
    response.end()
}

出bug就是因为自己太过自信了

找到bug之时,就是发现自己傻X之日

第一次讲console.log调试大法

console.log可以验证对错

针对之前的错误代码,可以在if判断前可以加上:

1
2
3
console.log("path:" + path);
console.log("path === './style.css:'");
console.log(path === './style.css');

false

不要相信自己,要相信console.log

答案揭晓:所有HTTP路径都是以/开头,./就访问不了,404了

把自己认为对的变量或者判断语句打出来


100元购买阿里云服务器

购买一台服务器

阿里云按量付费,即用即停 最低配,按量计费,Ubuntu 64

为什么要用收费的服务器

好处

  • 一个你可以完全自由掌控的Linux机器
  • 一个其他人可以访问的IP
  • 可以作为博客、作品展示、简历展示
  • 速度快于GitHub
  • HK地区机器,可作为FQ代理,但不能备案,所以不选
  • 如果备案了,还可以把域名绑定到这台机器

代价

  • 100RMB用1000hrs
  • 记得关服务器

购买阿里云服务器

流程

  1. 注册账号
  2. 进入云服务器ECS(可以搜索)
  3. 创建实例->按量付费->入门级->最便宜或打折优惠
  4. 镜像选Ubuntu 18.04 64位,最容易搜教程
  5. 其他不改,下一步
  6. 充值100
  7. 公网宽带选按流量+1s,哦不按流量+1Maps
  8. 其他不改,下一步
  9. 勾选服务协议,创建实例,弹出界面点击管理控制台
  10. 等待实例启动成功,状态变为运行中
  11. 购买完毕

允许8888端口

加入安全组

流程

  1. 更改实例规格>更多>网络和安全组>加入安全组,点击加入安全组
  2. 如果没有安全组,就新建一个
  3. 加入之后,更改实例规格>更多>网络和安全组>安全组配置,点击安全组配置
  4. 点击配置规则
  5. 点击添加安入组规则
  6. 端口填写8888/8888,(任意超过1234,小于65535的范围比如8000/8999
  7. 授权对象填写0.0.0.0/0表示任何人都能访问
  8. 点击确定,并输入手机验证码
  9. 此时,就可通过http://实例IP:8888访问了

请根据实际场景设置授权对象的CIDR,另外,0.0.0.0/0 代表允许或拒绝所有IP的访问,设置时请务必谨慎。参考帮助文档

使用服务器

流程

  1. 重置实例密码:更改实例规格>更多>密码/密钥>重置实例密码
  2. 填写新的密码两次和手机验证码
  3. 实例状态->重启实例
  4. 重启完了后点击远程连接
  5. 复制远程密码
  6. 在实例上新建标签,键为key,值为复制的密码
  7. 再次点击远程连接,输入连接密码
  8. login:后输入root
  9. password:输入密码,输入的时候没有反应为正常情况

现在,已经有一台Linux机器,不管是阿里云上的,还是本地的虚拟机

具体过程可能改版更新,密码可以随时修改,远程连接码不一定使用,使用实例密码即可

服务器配置

ssh远程登录

流程

  1. 首先登陆root账户(阿里云网页登陆或者其他)
  2. 成功看到Welcome...
  3. 把本地的SSH公钥复制到~/.ssh/authorized_keys,用echo 'xxx公钥' >>
  4. 建议把上面命令在VSCode上编辑好再复制
  5. 新建终端,在本地运行ssh root@实例IP
  6. 看到Welcome to Alibaba Cloud Elastic Compute Service !后,此时,就可以在本地终端用ssh操作云服务器了

成功界面

Welcome to...

exit退出,logout

刚才做了什么

  • 把本地的公钥复制到阿里云的~/.ssh/authorized_keys
  • 在本地用ssh root@实例IP来远程操作云机器
  • 以后都用ssh root@实例IP的方式即可
  • 可以在hosts里给实例IP取个别名
  • 要退出云机器,输入exit,回车
  • 如果卡了,直接Ctrl + w退出终端

如何防止ssh卡住(可跳过)

  • /etc/ssh/ssh_config最后加下面两句话

    1
    2
    
    Host *
    ServerAliveInterval 30
  • 用VScode打开这个文件会失败

  • 可以用两次echo搞定

    1
    2
    
    echo "Host *" >> /etc/ssh/ssh_config
    echo "ServerAliveInterval 30" >> /etc/ssh/ssh_config
  • 不要少写了空格

  • 重启终端生效,如果没有就重启

  • 从这里抄来的

  • 工具能用就行

创建普通应用账户

为什么

Linuxroot账户拥有最高权限,一旦被攻克…

步骤

  1. root账户账户下
  2. adduser yourname注意必须都小写
  3. Enter new UNIX password:输入密码
  4. 再次输入密码,可以和root的一样
  5. 一直回车,直到结束,运行如下命令

    1
    2
    3
    4
    
    mkdir /home/yourname/.ssh #创建路径
    cp ~/.ssh/authorized_keys /home/yourname/.ssh/ #复制公钥
    chmod 755 /home/yourname/.ssh/authorized_keys #将路径变为可读
    chown yourname:yourname /home/yourname/.ssh/authorized_keys #把key的拥有者变更为登录用户

现在ssh yourname@实例IP就可以使用了

多账户示意:

  • ssh root@ip访问root /root
  • ssh frank@ip访问frank /home/frank

sudo

user添加sudo权限

adduser username sudo

sudo是什么

  • 全称super user do
  • 类似于win的「以管理员身份运行」
  • 平时不该使用root账户,而是frank账户
  • 遇到特殊操作,就在前面加sudo,请出root
  • 需要输入frank的密码,不是root的密码
  • 使用ctrl + a可以快速回到命令前面,ctrl + e到最后
  • sudo!!的意思是用sudo执行上一句命令
  • 比如运行apt-get update更新包

部署 Node.js 代码

安装过Node.jsgit的可跳过,直接看### 部署应用

安装Node.js 8.x+

流程

1
2
3
4
5
6
7
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
sudo sed -i 's/deb.nodesource.com\/node_12.x/mirrors.tuna.tsinghua.edu.cn\/nodesource\/deb_12.x/g' /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install -y nodejs
node -v
npm -v
npx -v

安装git

命令

1
2
3
sudo apt install git
# 遇到[Y/n]输入回车,或者y回车
git --version

注意

  • 由于远程无界面环境,安装不了VSCode,虽然vim可以
  • 不使用git commit -v,改用git commit -m "xxx"
  • 如果想学习vim,在本地电脑输入vimtutor看完
  • 一开始不要浪费时间学vim,推荐若愚的vim教程
  • 自行搜报错信息
  • 实在不行,就去阿里云页面重启机器即可

部署应用

下载代码

1
git clone https://github.com/FrankFang/nodejs-test.git

这个地址可以改成仓库的https地址,只是下载测试,所以不要使用ssh地址,使用https

启动应用2

  1. cd nodejs-test
  2. touch log
  3. 启动命令:node server.js 8888 > log 2>&1 &
  4. 把启动命令做成start文件:touch start
  5. 添加可执行权限:chmod +x ./start,使其可执行带rw-x
  6. 运行sh ./start得到一个进程号pid,记下来,比如是:[1] 19225
  7. tail loglog内容
  8. kill -9 pid可以关掉进程,即kill -9 19225
  9. killall node可以关掉所有node进程

如何重启应用

上传代码

本地改完代码后,git push

下载代码2

  • ssh frank@实例IP
  • cd nodejs-test/
  • git pull
  • killall node(因为忘了进程号,实际上可以记下来)
  • sh./start
  • 重启完毕

回顾

  • 请求和响应分别有那几部分
  • 请求动词有哪些
  • 状态码有哪些
  • curl构造请求
  • Node.js读取请求,造响应
  • HTML/CSS/JS本质都是字符串
  • 部署Node.js应用到云服务器

阿里云停机操作

记得用完服务器机器要关机(并选择停止计费)

记得用完服务器机器要关机(并选择停止计费)

Node.js 初体验

方便大家复制的代码

1
2
3
4
5
6
curl -v http://127.0.0.1:8888

request.getHeader('Accept')
response.statusCode = 200
response.setHeader('Content-Type', 'text/html');
response.write('内容')

有问题的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if(path === '/'){
  response.statusCode = 200
  response.setHeader('Content-Type', 'text/html;charset=utf-8')
  response.write(`
    <link rel="stylesheet" href="./style.css">
    <h1>你好</h1>
  `)
  response.end()
} else if(path === './style.css'){
  response.statusCode = 200
  response.setHeader('Content-Type', 'text/css;charset=utf-8')
  response.write(`h1{color: red;}`)
  response.end()
} else {
  response.statusCode = 404
  response.end()
}

ssh 远程登录

1
echo '复制本地~/.ssh/id_rsa.pub内容' >> ~/.ssh/authorized_keys

防止 ssh 卡住

1
2
echo "Host *" >> /etc/ssh/ssh_config
echo "  ServerAliveInterval 30" >> /etc/ssh/ssh_config

创建应用账户

1
2
3
4
5
6
7
adduser frank
mkdir  /home/frank/.ssh
cp ~/.ssh/authorized_keys /home/frank/.ssh/
chmod 755 /home/frank/.ssh/authorized_keys
chown frank:frank /home/frank/.ssh/authorized_keys

adduser frank sudo

安装 Node.js 8和git

1
2
3
4
5
6
7
8
9
curl -sL https://deb.nodesource.com/setup_8.x | sudo bash -
sudo sed -i 's/deb.nodesource.com\/node_8.x/mirrors.tuna.tsinghua.edu.cn\/nodesource\/deb_8.x/g' /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install -y nodejs
node -v
npm -v
npx -v

sudo apt install git

部署应用2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
git clone https://github.com/FrankFang/nodejs-test.git
cd nodejs-test
touch log
启动命令:node server.js 8888 > log 2>&1 &
把启动命令做成 start 文件
添加执行权限 chmod +x ./start
运行 sh ./start 得到一个进程号 pid
tail log 看 log 内容
kill -9 pid 可以关掉进程
killall node 可以关掉所有 node 进程

如何重启应用2

1
2
3
4
5
ssh frank@实例ip
cd nodejs-test
git pull
killall node(因为忘了进程号,实际上可以记下来)
sh ./start

强烈建议购买阿里云服务器最低配

!记得用完服务器机器要关机(并选择停止计费!)


·未完待续·

参考文章

相关文章