Git本地端操作

安裝 git請參閱
檢查 git 版本 指令

1
2
git  ---version
git version 2.15.0

git

列出目前設定的參數:git config –list

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
46
47
48
49
50
51
52
53
54
//指令:列出目前設定的參數
git config --list
如下
core.excludesfile=~/.gitignore
core.legacyheaders=false
core.quotepath=false
mergetool.keepbackup=true
push.default=simple
color.ui=auto
color.interactive=auto
repack.usedeltabaseoffset=true
alias.s=status
alias.a=!git add . && git status
alias.au=!git add -u . && git status
alias.aa=!git add . && git add -u . && git status
alias.c=commit
alias.cm=commit -m
alias.ca=commit --amend
alias.ac=!git add . && git commit
alias.acm=!git add . && git commit -m
alias.l=log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'
alias.ll=log --stat --abbrev-commit
alias.lg=log --color --graph --pretty=format:'%C(bold white)%h%Creset -%C(bold green)%d%Creset %s %C(bold green)(%cr)%Creset %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
alias.llg=log --color --graph --pretty=format:'%C(bold white)%H %d%Creset%n%s%n%+b%C(bold blue)%an <%ae>%Creset %C(bold green)%cr (%ci)' --abbrev-commit
alias.d=diff
alias.master=checkout master
alias.spull=svn rebase
alias.spush=svn dcommit
alias.alias=!git config --list | grep 'alias\.' | sed 's/alias\.\([^=]*\)=\(.*\)/\1\ => \2/' | sort
include.path=~/.gitcinclude
include.path=.githubconfig
include.path=.gitcredential
diff.exif.textconv=exif
user.name=lara huang
user.email=lara1105huang@gmail.com
core.excludesfile=/Users/larahuang/.gitignore_global
core.autocrlf=false
difftool.sourcetree.cmd=opendiff "$LOCAL" "$REMOTE"
difftool.sourcetree.path=
mergetool.sourcetree.cmd=/Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"
mergetool.sourcetree.trustexitcode=true
commit.template=/Users/larahuang/.stCommitMsg
color.ui=true
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=git@github.com:lara1105huang/blog_lara.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main

設定使用者名稱及信箱(總體)

1
2
git config --global user.name、
git config --global user.email

設定查看配置

1
2
git config --global --list
git config --local --list

Git本地端操作

新增版控初始化

1
2
3
4
5
mkdir 資料夾名稱 //新增資料夾名稱
cd 資料夾名稱 //到資料夾內
git init //加入版控,初始化

Initialized empty Git repository in /Users/larahuang/Desktop/2023-10m/newtest/.git/

為什麼我看不到隱藏檔案
Mac=>

如何停止整個版本控制

1
rm -r .git

版控內的忽略檔案(不加入版控寫在這個檔案內)
新增 .gitignore

1
touch .gitignore //新增 .gitignore版控內的忽略檔案

時常檢查狀態

1
git status

取消追蹤

1
git rm --cached <file>

本地端又分為:

工作目錄(Working Directory)
放入暫存區(Stating Area)
1
git add .
### 加入本地端儲存庫
1
git commit -m '版本訊息'
本地端檔案庫(local repo)
1
git commit -am 'message'

檢視 commit 紀錄

1
git log

輸出更簡潔的 log

1
git log —-oneline
# 指令 解析
1 $git config global user.name 配置name
2 $git config global user.email 配置email
1-1查看配置 $ git config --list 列出目前設定的參數
1-2查看配置 $ git config --global --list 查看當前global用戶配置
1-2查看配置 $ git config --local --list 查看當前local用戶配置
3 .gitignore 忽略檔案,新增.gitignore 加入要忽略的檔案
4.1 $ git init 新增版控,初始化
4.2 $ rm -r .git 停止整個版本控制
4.3 $ git add . 放入暫存區
4.4 $ git status 時常檢查狀態
4.5 $ git rm --cached 取消追蹤
4.6 $ git log 檢視 commit 紀錄
4.7 $ git log --oneline 檢視 輸出更簡潔的 log
4.8 $ git log 檔案名稱 檢視 檔案名稱
4.9 $ git rm 檔案名稱 刪除檔案
4.10 $ $ git rm --cached welcome.html 讓檔案不再受 git 版控(並不是刪除!)
4.11 $ git mv
ex. $ git mv welcome.html hello.html
變更檔名
4.12
$ git checkout
ex.切換到最新版本:$ git checkout master
切換版本/分支
4.13
$ git diff
ex.比對工作目錄與暫存區(Stating Area)全部檔案的差異:$ git diff --cached
ex.比對當前文件與暫存區(Stating Area)全部檔案的差異:$ git diff filename
比對工作目錄(Working Directory)與指定 commit 之間的差異 :$ git diff commit-id
比對兩個 commit 之間的差異 $ git diff [commit-id][new commit-id]
比對兩個 branch 之間的差異 $ git diff branch1 branch2
比對工作目錄

git 參考資料

style Prettier 套件 - 自動整理程式碼格式

套件husky,lint-staged,eslint

husky

1
npm install husky lint-staged -D
1
npm install -g eslint 

在 package.json 檔案中加上套件相關資訊

1
2
3
4
5
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write"
]
}

在 VSCode 安裝 prettier

設定在存檔時執行 prettier,在設定中把 Format on Save 選項打勾:

<img style="margin-top:10px" src="https://blog-lara.vercel.app/images/prettier/form_on_save.png">

<div>參考資料</div>
<a href="https://titangene.github.io/article/javascript-object-keys-values-entries.html" target="_blank">參閱prettier</a>

Git安裝

安裝 git

method法一、官網下載
適用:windows、Mac OS X
跟一般的軟體安裝方式相同:下載、安裝、執行。

method二、Homebrew 下載
適用:Mac OS X

Homebrew是一款自由及開放原始碼的軟體套件管理系統,用以簡化 macOS系統上的軟體安裝過程。

1.在終端機上輸入以下指令就可以安裝

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homwbrew/install/master/instakk.sh)"

2.接著安裝 git 輸入

1
brew install git

3.檢查 git 版本

1
2
git  ---version
git version 2.15.0

javascript 搜尋陣列中的物件

“陣列”由方括號 [] 表示,而”物件”由大括號 {} 表示。

使用forEach迴圈判斷物件宣染到畫面

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
//html
<ul class="list">
<li><span></span></li>
</ul>


<script>
//陣列arrays
const arrays = [
{ name:"Adam", profession:"Engineer", company: "Google" },
{ name:"Sam", profession:"Manager", company: "Amazon" },
{ name:"Gerogia", profession:"Designer", company: "Netflix" },
{ name:"Kate", profession:"Engineer", company: "Microscoft" },
{ name:"James", profession:"Sales", company: "Amazon" },
];

//綁定
const list =document.querySelector('.list');
let str='';
arrays.forEach(item =>{
if(item.company==='Amazon'){
str +=`<li><span>${item.name}</span></li>`
}
})
list.innerHTML = str;
</script>

使用map()迴圈判斷物件宣染到畫面

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
//html
<ul class="list">
<li><span></span></li>
</ul>


<script>
//陣列arrays
const arrays = [
{ name:"Adam", profession:"Engineer", company: "Google" },
{ name:"Sam", profession:"Manager", company: "Amazon" },
{ name:"Gerogia", profession:"Designer", company: "Netflix" },
{ name:"Kate", profession:"Engineer", company: "Microscoft" },
{ name:"James", profession:"Sales", company: "Amazon" },
];

//綁定
const list =document.querySelector('.list');
let str='';
arrays.map(item =>{
if(item.company==='Amazon'){
return str +=`<li><span>${item.name}</span></li>`
}
})
list.innerHTML = str;
</script>

使用find迴圈判斷物件宣染到畫面

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
//html
<ul class="list">
<li><span></span></li>
</ul>


<script>
//陣列arrays
const arrays = [
{ name:"Adam", profession:"Engineer", company: "Google" },
{ name:"Sam", profession:"Manager", company: "Amazon" },
{ name:"Gerogia", profession:"Designer", company: "Netflix" },
{ name:"Kate", profession:"Engineer", company: "Microscoft" },
{ name:"James", profession:"Sales", company: "Amazon" },
];

//綁定
const list =document.querySelector('.list');
let str='';
arrays.find(item =>{
if(item.company==='Amazon'){
str +=`<li><span>${item.name}</span></li>`
}
})
list.innerHTML = str;
</script>

js switch

範例1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let animal = '狗';
//這是錯誤範例
switch (animal) {
case '貓':
console.log('喵');
case '狗':
console.log('汪'); //汪
case '雞':
console.log('咕'); //咕
case '羊':
console.log('咩'); //咩
default:
console.log('無此動物'); //無此動物
}
將「表達式的值」與「case 條件裡的值」做比對,執行符合此條件下方的陳述式
js_switch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let BMI = 34;

switch (true) {
case BMI >= 35:
console.log('重度肥胖');
break;
case BMI < 35 && BMI >= 30:
console.log('中度肥胖');
break;
case BMI < 30 && BMI >= 27:
console.log('輕度肥胖');
break;
case BMI < 27 && BMI >= 24:
console.log('過重');
break;
case BMI < 24 && BMI >= 18.5:
console.log('正常');
break;
default:
console.log('過輕');
}

js typeof 判斷型別

typeof

JavaScript 的內建七種型別有 number、string、boolean、null、undefined、object、symbol

string
1
2
3
var title="這是測試";
console.log(typeof title)
'string'
number
1
2
3
var numberValue = 1;
typeof numberValue
'number'
Object
1
2
3
4
5
6
7
var lists= [
{title:'首頁',href:'home'},
{title:'關於我',href:'about_us'},
{title:'登入',href:'login'},
];
typeof lists
'Object'
boolean
1
2
3
var isOpen = true;
typeof isOpen
'boolean'
undefined
1
2
typeof i
'undefined'
symbol
1
2
3
const sym1 = Symbol();
typeof sym1
'symbol'
null
1
2
3
4
5
6
const foo = null;
if(foo == null){
console.log('null')
}
typeof foo;
'symbol'
Null參考資料

js 物件轉陣列的迴圈

實戰api串接或是第三方資料,不是所有資料都是給予“陣列”,就無法使用如:forEach、map、reduce、find… 迴圈,物件資料如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//物件形式
const roles = {
'001': {
name: '海綿寶寶',
expert: '吸收很快',
},
'002': {
name: '耶夢',
expert: '任意門',
},
'004': {
name: '超人',
expert: '英雄',
},
};

錯誤示範是使用forEach
要對物件使用陣列方法,ES6 的語法對物件使用陣列方法=>將物件轉為陣列

  • Object.values
  • Object.keys
  • Object.entries

使用 Object.values 物件轉陣列forEatch迴圈

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
const roles = {
'001': {
name: '海綿寶寶',
expert: '吸收很快',
img:'https://cdn.pixabay.com/photo/2017/05/08/13/15/bird-2295431_1280.jpg'
},
'002': {
name: '耶夢',
expert: '任意門',
img:'https://cdn.pixabay.com/photo/2015/11/16/16/28/bird-1045954_1280.jpg'
},
'004': {
name: '超人',
expert: '英雄',
img:'https://cdn.pixabay.com/photo/2017/05/08/13/15/bird-2295431_1280.jpg'
},
};
//綁定
const list = document.querySelector('.list');
//let 觀念
let str = "";
//Object.values 與 forEach
Object.values(roles).forEach((item) => {
console.log(item);
//加法赋值运算符
str +=
`<li class="card col-md-3 mb-2">

<span class="card-body">
<span style="width:50px;height:50px;overflow:hidden"><img src="${item.img}" style="width:80px;height:auto;"></span>
<span><b>${item.name}</b></span>
專業能力:
<span> ${item.expert} </span>
</span>
</li>`;
});
list.innerHTML = str;

使用 Object.keys物件轉陣列forEatch迴圈

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
const roles = {
'001': {
name: '海綿寶寶',
expert: '吸收很快',
},
'002': {
name: '耶夢',
expert: '任意門',
},
'004': {
name: '超人',
expert: '英雄',
},
};
//綁定
const list = document.querySelector('.list');
//let 觀念
let str = "";
Object.keys(roles).forEach((key) => {
console.log(roles[key]);
str +=
`<li class="card col-md-3 mb-2">
<span><b>${roles[key].name}</b></span>
<spanclass="card-body">
專業能力:
<span> ${roles[key].expert} </span>
</span>
</li>`;
});
list.innerHTML = str;

使用 Object.entries 物件轉陣列forEatch迴圈

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
const roles = {
'001': {
name: '海綿寶寶',
expert: '吸收很快',
},
'002': {
name: '耶夢',
expert: '任意門',
},
'004': {
name: '超人',
expert: '英雄',
},
};
//綁定
const list = document.querySelector('.list');
//let 觀念
let str = "";
Object.entries(roles).forEach((obj) => {
console.log(obj[0], obj[1]);
str +=
`<li class="card col-md-3 mb-2">
<span><b>${obj[0].name, obj[1].name}</b></span>
<span class="card-body">
專業能力:
<span> ${obj[0].expert, obj[1].expert} </span>
</span>
</li>`;
});
list.innerHTML = str;
參考資料
參閱mozilla Object.values() 參閱Object.keys() & Object.values() & Object.entries()

javascript 將兩個陣列合併

Part1

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
let arr1 = [
{ id: "abdc1234", date: "2023-10-17" },
{ id: "abdc1235", date: "2023-10-18" }
];

let arr2 = [
{ id: "abdc1234", name: "lara" },
{ id: "abdc1235", name: "sara" }
];

let arr3 = arr1.map((item, i) => Object.assign({}, item, arr2[i]));
console.log(arr3);


[
{
"id": "abdc1234",
"date": "2023-10-17",
"name": "lara"
},
{
"id": "abdc1235",
"date": "2023-10-18",
"name": "sara"
}]

參考資料
javascrit map() 遍歷產生一個陣列
Object.assign() 枚舉

Part2 for迴圈與查找相同id 新增

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
let arr1 = [
{ id: "abdc1234", date: "2023-10-17" },
{ id: "abdc1235", date: "2023-10-18" }
];

let arr2 = [
{ id: "abdc1234", name: "lara" },
{ id: "abdc1235", name: "sara" }
];

let merged = [];

for(let i=0; i<arr1.length; i++) {
merged.push({
...arr1[i],
...(arr2.find((itmInner) => itmInner.id === arr1[i].id))}
);
}


console.log(merged);

[
{
"id": "abdc1234",
"date": "2023-10-17",
"name": "lara"
},
{
"id": "abdc1235",
"date": "2023-10-18",
"name": "sara"
}]

參考資料
javascrit map() for()
push() 添加一個或多個元素至陣列的末端
find()

Part3 for迴圈與擴展運算子的合併

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
let arr1 = [
{ id: "abdc1234", date: "2023-10-17" },
{ id: "abdc1235", date: "2023-10-18" }
];

let arr2 = [
{ id: "abdc1234", name: "lara" },
{ id: "abdc1235", name: "sara" }
];
let merged = [];

for(let i=0; i<arr1.length; i++) {
merged.push({
...arr1[i],
...arr2[i]
});
}

console.log(merged)
[
{
"id": "abdc1234",
"date": "2023-10-17",
"name": "lara"
},
{
"id": "abdc1235",
"date": "2023-10-18",
"name": "sara"
}]

參考資料
javascrit map() for()
javascript(ES6)擴展運算子 Spread Operator

Node express MongoDB 註冊與登出api

註冊使用到以下功能

  • cors 跨來源資源共用
  • bcryptjs密碼加密
  • jsonwebtoken用戶身份驗證

使用者定義Schema

請參閱
在models資料夾內新增 userModel.js

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
46
47
48
49
50
51
52
53
54
55
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')
const moment = require('moment')
moment().format();
const timezone = -(new Date().getTimezoneOffset() / 60) + 8;
const time = moment(Date.now() + (timezone * 60 * 60 * 1000)).format('YYYY-MM-DDT HH:mm').toString();
//console.log('timezone', timezone)

const userSchema = mongoose.Schema(
{
username: {
type: String,
required: [true, "請輸入使用者2~30字符"],
trim: true,
match: [
/^.{2,30}$/,
'Please add a valid name 2~30字符',
],
},
email: {
type: String,
required: true,
match: [
/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
'Please add a valid email',
],
},
password: {
type: String,
required: [true],
trim: true,
},
created:
{
type: String,
default: time
},
token: {
type: String,
}
},

)
//findByEmail 函式
userSchema.statics.findByEmail =async (email) =>{
//查找User 是否有該email
const user = await User.findOne({ email })
//如果有
if (user) { throw new Error('已經有該用戶!') }
return user
}

const User = mongoose.model('User', userSchema);

module.exports = User;

註冊與登入

驗證的路由必須要 middleware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//verifyToken
const verifyToken = (req, res, next) =>
{
const bearerHeader = req.headers.authorization;
if (typeof bearerHeader !== 'undefined') {
const bearer = bearerHeader.split(' ');
const bearerToken = bearer[1];
req.token = bearerToken;
next();
}
else {
req.send({result:'令牌無效!'})
}
}
module.exports = verifyToken;

註冊與登入& 驗證

引入 userModel.js
引入jwt,bcrypt,verifyToken
bcrypt.hashSync :bcrypt加密
bcrypt.compare() :bcrypt驗證密碼
引入 jwt sign()驗證 token
jwt & bcrypt 筆記

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const express = require('express')
const verifyToken = require('../middleware/token')
const User = require('../models/userModel')
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const router = express.Router()

//註冊
router.post('/register', async(req, res) =>
{
try {
/*
#swagger.summary='註冊',
#swagger.description = '' */
/* #swagger.parameters['body'] = {
in: 'body',
description: '',
required: true,
schema: { $ref: "#/definitions/AddUser" }
} */

/* #swagger.security = [{
"apiKeyAuth": []
}] */
const data = new User(req.body);
//註冊時,Email使用 findByEmail 函式驗證
const email = await User.findByEmail(req.body.email)
data.password = bcrypt.hashSync(req.body.password, 12);

const token = jwt.sign({ _id: data._id ,username: data.username,email: data.email}, 'RESTFULAPI',{expiresIn: "24h"}).toString();
let userArr = {
username: data.username,
email: data.email,
password: data.password,
created: data.created,
token:token
}

const user = await User.create(userArr);
res.status(200).json(user);
}
catch (error) {
res.status(500).json({message: error.message})
}
})


//登入
router.post('/login',async (req, res) =>{
const { email, password } = req.body;
try {
/*
#swagger.summary='登入',
#swagger.description = '' */

/* #swagger.parameters['body'] = {
in: 'body',
description: '',
required: true,
schema: { $ref: "#/definitions/Login" }
} */

/* #swagger.security = [{
"apiKeyAuth": []
}] */
let user = await User.findOne({email});
if (!user)
return res.status(400).json({message: "用戶不存在"});

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch)
return res.status(400).json({message: "密碼錯誤 !"});

const payload = {
user: {id: user.id}
};

jwt.sign(payload,user.email,{expiresIn: 3600},(err, token) => {
if (err) throw err;
res.status(200).json({token});
}
);
}
catch (e) {
console.error(e);
res.status(500).json({
message: "伺服器錯誤!"
});
}
})


//users驗證
router.delete('/users/:id', verifyToken,async(req, res) =>{
try {
/*
#swagger.tags = ['以下請先登入'],
#swagger.summary='刪除使用者',
#swagger.description = '' */
const {id} = req.params;
const user = await User.findByIdAndDelete(id);
if(!user){
return res.status(404).json({message: `沒有發現任何使用者 ${id}`})
}
res.status(200).json(user );

} catch (error) {
res.status(500).json({message: error.message})
}
})


router.post("/welcome", verifyToken, (req, res) =>
{
/*
#swagger.tags = ['以下請先登入'],
#swagger.summary='歡迎畫面',
#swagger.description = '' */
console.log('req.body', req.body)
res.status(200).send("Welcome 🙌 ");
});

module.exports = router;

node express jwt 註冊與登出
bcrypt
bcrypt筆記本
Node 實作 jwt 驗證 API
How To Implement API Authentication with JSON Web Tokens and Passport
OAuth 2.0
OAuth 2.0

關於HTTP

什麼是HTTP

HTTP 全名是Hypertext Transfer Protocol,中文是超文本傳輸協定,是一個網路應用層的協定,讓電腦之間可以互相傳輸資訊。

HTTP如何運作

HTTP遵循客戶端(client)-伺服器端(server)的模式
client =>(發送請求,request) => server(根據請求內容) =>(發送回應,response)=>client

圖片來源https://bytesofgigabytes.com/networking/how-http-request-and-response-works/

### HTTP的內容 擷取MDN針對這四個部分的概覽:
  • Start Line: A start-line describing the requests to be implemented, or its status of whether successful or a failure. This start-line is always a single line.
    Start Line:描述要實現的請求或其成功或失敗狀態的起始行。 此起始線始終是單行。
  • HTTP headers: An optional set of HTTP headers specifying the request, or describing the body included in the message. Empty Line: A blank line indicating all meta-information for the request has been sent.
    HTTP 標頭:一組可選的 HTTP 標頭,用於指定請求或描述訊息中包含的正文。 空白行:空白行指示請求的所有元資訊已發送。
  • Body: An optional body containing data associated with the request (like content of an HTML form), or the document associated with a response. The presence of the body and its size is specified by the start-line and HTTP headers.
    Body:包含與請求關聯的資料(如 HTML 表單的內容)或與回應關聯的文件的可選正文。 正文的存在及其大小由起始行和 HTTP 標頭指定。

圖片來源:MDN HTTP Messages

Request發送請求

  1. Start Line:包含三個部分
    • Method: 請求的方法,是GET, PUT, POST等等的動詞,不同的動詞有不同的使用場景
    • Request target: 請求的目標 請求的目標,通常是網址,也就是網路資源存放的地方,根據不同的method,會有不同的格式,可以看我之前寫的GET vs. POST的不同。
    • HTTP version request使用的http版本
  2. HTTP headers
    資料來源MDN
    • host: 這個request是send給誰的(server的網址)
    • accept:這個request是要接受哪些類型(content-types)的資料 比方說text或是json檔案
    • cookie:瀏覽器存放的cookie字串
  3. Body: Request的Body一樣會根據不同的method而有所不同,一般來說GET、DELETE不會帶有body,POST則會把資訊放入body裡面。在使用HTML表單時,如果用表單送一個POST request,就會把表單內容放入body。

Response發送回應

  1. Start Line: 一樣包含三個部分,需要注意的是並沒有method和URL
    • HTTP version
    • Status Code: 這是response start line最重要的部分,server利用status code來告訴client這個request到底是成功還是失敗。status code根據不同 資料來源
      1
      2
      3
      4
      5
      - Informational responses (100–199)
      - Successful responses (200–299)
      - Redirects (300–399)
      - Client errors (400–499)
      - Server errors (500–599)
      一般使用者最常看到的就是404:頁面不存在,除了4xx,在開發時常用的還有200 (OK)、3xx (Redirect)、5xx (Server error)。
    • Status text:簡短的和使用者說明status code是什麼意思,比方說404 Not Found。
  2. HTTP headers:列出一些常見的
    • Status: 就是status code,例如200
    • Server: 透過什麼web server來回應的,比方說Apache
    • content-type: 這個response檔案是什麼類型
    • set-cookie: server端要設定在client端的cookie
  3. Body: response的body會帶著server要回傳給client的資料。對前端開發者來說,通常是json檔案,前端開發者要處理的邏輯就是把接收的json檔案轉換成畫面,渲染給終端使用者看