、http基礎篇
簡介
http(超文本傳輸文本協議), 用于web應用傳輸數據的協議, 只能由客戶端發起, 由服務端響應。 具有無狀態等特點。
結構
http協議的傳輸單位是http報文(請求報文、響應報文)。 報文的結構可分為:請求/響應行、 首部字段、實體部分。
get請求報文
GET /index.html HTTP/1.1 //請求行
Host: test.com //首部字段
1
2
3
get響應報文
HTTP/1.1 200 OK //響應行
Date: Tue, 10 Jul 2012 06;50:15 GMT //首部字段
Content-Length: 362 //首部字段
Content-Type: text/html //首部字段
<html> //實體
...
1
2
3
4
5
6
7
請求行用于說明請求方法 , 請求地址, http版本號
響應行用于說明服務器http版本號, 響應狀態碼, 狀態碼的原因短句
首部字段分為: 通用首部字段、 請求首部字段、 響應首部字段、 實體首部字段
對于實體內的內容, 可以用實體首部字段加以說明。 最常使用的是content-type: xxxx, 說明實體內容的類型。
二、javaScript操作http
瀏覽器中, http請求可以由瀏覽器中的如下內容發送:
1. 瀏覽器中的url地址欄
2. 頁面有src屬性的標簽(img、script、 link等)
3. 帶有action屬性的form表單
4. XMLHttpRequest對象
1. XMLHttpRequest的基本用法
在這些方法中, XMLHttpRequest對象提供了接口讓我們操作http.基本用法如下:
var xhr = new XMLHttpRequest();//此時readyState屬性值為0
xhr.open('post', 'http://www.test.com', false)//此時readyState屬性值為1
xhr.send("name=yang&psd=123")//readyState屬性值為2
xhr.onreadyStatechange = function(){
if(xhr.readState === 4 && xhr.status === 200 ){
console.log(xhr.responseText)
}else{
console.log('Request was unsuccessfull:' + xhr.status)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
以上是XMLHttpRequest的基本使用方法。
1). 發送數據, 使用send方法
這里的發送數據指的是post方法發送數據
xhr.send("name=yang&psd=123")//post方法發送了一個form表單數據
1
如果是get方法則數據拼接到url后面(使用encodeURIComponent()將名和值進行編碼之后), send方法參數必須是null
xhr.open('get', 'http://www.test.com?name='yang'&psd=123, false)//將name和value進行encodeURIComponent編碼, (同cookie的value一樣), 其中open方法最后一個參數代表是否異步
xhr.send(null)//不能不寫
1
2
2). 使用readyState可以查看當前xhr對象的狀態, 狀態有:
0– 沒調用open方法
1– 沒調用send方法
2– 調用send方法, 未接受到響應
3– 正在接受響應, 未接受完成
4– 響應全部接受
3). 獲得響應的狀態, 使用status屬性, 當屬性的值為200表示請求成功
var httpStatus = xhr.status
if(httpStatus === 200){
//請求成功,可以做接下來的事情了
}
1
2
3
4
4). 獲得響應的數據,使用responseText屬性
var result = xhr.responseText
1
5). 添加首部字段, 使用setRequestHeader方法
xhr.setRequestHeader('myHeader', 'myValue')//這里必須放在open方法, 和send方法中間, 否則不能成功添加首部字段
1
6). 獲得首部字段, 使用getResponseHeader或getAllResponseHeaders方法
var header = xhr.getResponseHeader('myHeader')//傳入首部字段名
var headers = xhr.getAllResponseHeader()//獲得全部的首部字段,返回多行文本內容
//這是headers的結果
Date: Sun, 14 Nov 2004 18:04:03 GMT
Server: Apache/1.3.29(Unix)
Vary: Accept
X-Powered-By: PHP/4.3.8
Connection: close
Content-Type: text/html;charset=ios-8859-1
1
2
3
4
5
6
7
8
9
10
2. XMLHttpRequest跨域用法
使用XHR對象通信,有一個限制就是跨域安全策略。 默認情況下, XHR對下只能訪問包含它的頁面位于同一個域中的資源。 但是有時我們開發不能不進行跨域請求。
1). CORS跨域源資源共享
基本思想: 使用自定義的首部字段讓給瀏覽器與服務器溝通, 從而決定請求或響應是否應該成功。
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息(Origin首部字段),有時還會多出一次附加的請求,但用戶不會有感覺。
2). 原理
客戶端
瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息(Origin首部字段),有時還會多出一次附加的請求(分簡單請求),但用戶不會有感覺。
服務端
服務器讀取Origin首部字段的值, 判斷是否應該成功, 如果成功返回的響應報文中首部字段包含Access-control-allow-Origin:xxxxxx。 如果xxxxx為*或與自己發送的Origin的值相同, 瀏覽器就會判斷請求成功。
3). CORS的簡單請求與非簡單請求
局限
CORS跨域請求, 存在以下限制, 例如:
求方法為post/get/head,
首部字段只設置Content-Type
不能訪問響應頭部
cookie不隨請求發送
簡單情求
請求方法為post/get/head, 首部字段只設置content-type(只限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain等
), 這樣的請求為簡單請求。 這是瀏覽器將會在請求報文中添加Origin的首部字段,完成情趣。
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
1
2
3
4
5
6
非簡單請求
如果不是簡單請求, 瀏覽器將不會想處理簡單請求一樣處理, 例如我們希望添加其他的首部字段。 這瀏覽器將會發送一個預檢請求(Preflighted Requests)
Preflighted Requests,如下
OPTIONS /cors HTTP/1.1 //請求的方法, 地址, http版本
Origin: http://api.bob.com // 客戶端的域名
Access-Control-Request-Method: PUT //即將發起非簡單請求的方法, 用于服務器判斷是否支持該方法
Access-Control-Request-Headers: X-Custom-Header //即將發起非簡單請求攜帶的首部字段, 用于服務器判斷是否支持該字段
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
1
2
3
4
5
6
7
8
這種請求的方法是options方法, 用于服務器詢問。 如果服務都滿足, 將會如下
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com //允許跨域的域
Access-Control-Allow-Methods: GET, POST, PUT //支持的請求方法
Access-Control-Allow-Headers: X-Custom-Header //支持的頭部
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
1
2
3
4
5
6
7
8
9
10
11
12
瀏覽器將會用響應報文的首部字段中以Access-control開頭的字段與即將發送的請求比對, 如果服務將會如同簡單請求一樣發送請求。 故,非簡單請求會有一個預檢請求。
同時, 瀏覽器會將響應按照這個時間:(Access-Control-Max-Age: 1728000)保存, 在該時間未過期期間, 就不必發送預檢請求, 而直接發起請求。
攜帶cookie
默認情況下, 跨域請求不會攜帶cookie。 需要我們設置一個屬性值–withCredentials
xhr.withCredentials = true
1
當然跨域攜帶cookie也需要服務器支持才行, 如果服務愿意接受攜帶cookie的跨域信息, 就會在預檢請求響應頭部添加如下首部字段:
Access-Control-Allow-Credentials: true
1
3. 跨瀏覽器的CORS
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest()
if("withCredentials" in xhr){
xhr.open(method, url, true);
}else if (typeof XDomainRequest() != 'undefined') {
xhr = new XDomainRequest()
xhr.open(method, url)
}else{
xhr = null
}
return xhr
}
var request = createCORSRequest('get', 'http://test.com')
if(request){
request.onload = function(){//XMLHttpRequest 2級增加的事件
//對request.responseText進行處理
}
request.send(null)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
總結
詳細了解http呢是有必要的, 對于我們理解很多東西都有非常大的好處。 比如這篇文章, 關于操作http部分, 其重點就是添加實體, 添加首部字段的操作。 而關于添加首部字段呢, 就有必要明白各個首部字段的意義了。
文共2678字,預計學習時長15分鐘
圖源:unsplash
使用JavaScript時,總會有各種需要發出調用請求的情況,進行ajax調用什么技術更適合呢?
最初,盡管有一些方法可以在不刷新頁面的情況下從服務器提取數據,但它們通常依賴于笨拙的技術。直到微軟為Outlook電子郵件客戶端的替代瀏覽器開發了XMLHttpRequest。它在2006年成為了Web標準。
2015年,Fetch API隨ES6引入。通用的Request和Response接口提供了一致性,而Promises允許更容易的鏈接和沒有回調的異步/等待。Fetch簡潔,優雅且易于理解,但是還有其他不錯的選擇,本文將簡要的含義、語法以及利弊。
以下代碼展示了使用不同替代方法的基本HTTP GET和POST示例。現在開始吧~
XMLHttpRequest對象可用于從Web服務器請求數據。它是這次比較中最早的方法,盡管其他選擇都優于它,但由于其向后兼容性和成熟度,它仍然有效且有用。
得到:
var req= new XMLHttpRequest();//The onreadystatechange property
//specifies a function to be
//executed every time the status
//of the XMLHttpRequest changes
req.onreadystatechange = function() {
if (this.readyState == 4 &&this.status == 200) {
//The responseText property
//returns a text string
console.log(xhttp.responseText)
//Do some stuff
}
};req.open("GET", "http://dataserver/users", true);
req.send();
發送:
varformData = new FormData();
formData.append("name", "Murdock");
var req = new XMLHttpRequest();
req.open("POST", "http://dataserver/update");
req.send(formData);
優點:
· 不需要從外部源加載
· 向后兼容性
· 成熟/穩定
· 在所有瀏覽器中均可使用
· 是原生瀏覽器API
缺點:
· 支持回調地獄
· 笨拙冗長的語法
· Fetch能自然地替代它
圖源:unsplash
Qwest是一個基于Promise的簡單ajax庫,它支持XmlHttpRequest2的獨立數據,例如ArrayBuffer,Blob和FormData。
得到:
qwest.get('http://dataserver/data.json')
.then(function(xhr, response) {
// ...do some stuff whith data
});
發送:
qwest.post('http://dataserver/update',{
firstname: 'Murdock',
age: 30
})
.then(function(xhr, response) {
// Make some useful actions
})
.catch(function(e, xhr, response) {
// Process the error
});
優點:
· 可以建立請求限制
· 基于Promise
缺點:
· 并非所有瀏覽器上都可使用XmlHttpRequest2
· 非原生
· 必須從外部源加載
該庫在不久前被廣泛用于發出HTTP異步請求。jQuery的所有Ajax方法都返回XMLHTTPRequest對象的超集
得到:
$.ajax({
url: 'http://dataserver/data.json'
}).done(function(data) {
// ...do some stuff whith data
}).fail(function() {
// Handle error
});
發送:
$.ajax({
type: "POST",
url: 'http://dataserver/update',
data: data,
success: successCallBack,
error: errorCallBack,
dataType: dataType
});
優點:
· 良好的支持和文檔
· 可配置的對象
· 在許多項目中使用
· 學習曲線低
· 它返回XMLHttpRequest對象,因此可以中止請求
缺點:
· 非原生
· 必須從外部源加載
· 沒有與Promises結合
· 對于原生ES6 Fetch不是必需的。
圖源:unsplash
基于Promise的HTTP庫,用于在瀏覽器和Nodejs上執行HTTP請求。
得到:
axios({
url: 'http://dataserver/data.json',
method: 'get'
})
發送:
axios.post('http://dataserver/update',{
name: 'Murdock'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
優點:
· 使用promise避免回調地獄
· 在瀏覽器和Nodejs上均可使用
· 支持上傳進度
· 可以設置響應超時
· 通過簡單地向其傳遞配置對象即可配置請求
· Axios已實現可撤銷的promise提議
· 自動將數據轉換為JSON
缺點:
· 非原生
· 必須從外部源加載
SuperAgent是ajax API,旨在提供靈活性,可讀性和較低的學習曲線。它也可以與Node.js一起使用。
得到:
request('GET','http://dataserver/data.json').then(
success, failure);
.query()方法接受對象,這些對象與GET方法一起使用時將形成查詢字符串。以下代碼將產生路徑/ dataserver / search?name = Manny&lastName = Peck&order = desc。
request
.get('/dataserver/search')
.query({ name: 'Templeton' })
.query({ lastname: 'Peck' })
.query({ order: 'desc' })
.then(res => {console.dir(res)}
});
發送:
request
.post('http://dataserver/update')
.send({ name: 'Murdock' })
.set('Accept', 'application/json')
.then(res => {
console.log('result' +JSON.stringify(res.body));
});
優點:
· 基于Promise
· 在Node.js和瀏覽器中均可使用
· 可以調用request.abort()方法中止請求
· 社區的知名庫
· 發出HTTP請求的無縫接口
· 出現故障時支持重試請求
缺點:
· 它不支持以XMLHttpRequest的形式監視加載進度
· 非原生
· 必須從外部源加載
圖源:unsplash
Http-client允許使用JavaScript的訪存API組成HTTP客戶端。
得到:
//usingES6 modules
import { createFetch, base, accept, parse } from 'http-client'const fetch =createFetch(
base('http://dataserver/data.json'),
accept('application/json'),
parse('json')
)fetch('http://dataserver/data.json').then(response => {
console.log(response.jsonData)
})
發送:
//usingES6 modules
import { createFetch, method, params } from 'http-client'const fetch =createFetch(
params({ name: 'Murdock' }),
base('http://dataserver/update')
)
優點:
· 在Node.js和瀏覽器中均可使用
· 由服務器端工作人員使用
· 基于Promise
· 提供頭部保護裝置,以提高CORS的安全性
缺點:
· 必須從外部源加載
· 非原生
Fetch是原生瀏覽器API,用于發出替代XMLHttpRequest的請求。與XMLHttpRequest相比,Fetch使網絡請求更容易。Fetch API使用Promises避免XMLHttpRequest回調地獄。
得到:
//WithES6 fetch
fetch('http://dataserver/data.json')
.then(data => {
// ...do some stuff whith data
}).catch(error => {
// Handle error
});
發送:
fetch('http://dataserver/update',{
method: 'post',
headers: {
'Accept': 'application/json,text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: 'Murdock'})
}).then(res=>res.json())
.then(res => console.log(res));//ORwith ES2017 for example(async () => {
const response = awaitfetch('http://dataserver/update', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body:JSON.stringify({name='Murdock'})
});const result = awaitresponse.json();console.log(result);
})();
優點:
· 是原生瀏覽器API
· Fetch基本上是經過完善的XMLHttpRequest
· 友好且易于學習
· 與大多數最近使用的瀏覽器兼容
· 是原生XMLHttpRequest對象的自然替代
· 學習曲線低
· 不需要從外部源加載它
· 使用promises避免回調地獄
· 不需要更多依賴項
缺點:
· 處理JSON數據的過程分為兩步。第一個是發出請求,然后第二個是在響應時調用.json()方法。對于Axios,默認情況下會收到JSON響應。
· 從Fetch()返回的Promise僅在網絡故障或任何阻止請求完成的情況發生時拒絕。即使響應為HTTP 404或500,也不會拒絕HTTP錯誤狀態。
· 缺乏其他庫的一些有用功能,例如:取消請求。
· 默認情況下,Fetch不會從服務器發送或接收Cookie,如果站點依賴于維持用戶會話,則會導致未經身份驗證的請求。但是可以通過添加以下內容來啟用:
{credentials: “same-origin.”}
圖源:unsplash
Fetch是一個新標準,新版本的Chrome和Firefox無需使用任何其他庫就可支持它。
此外,Axios,SuperAgent或其他庫都有適合的文檔,易于使用,并且學習曲線不太高。在某些情況下,它們可以提供Fetch不具有的功能。
Fetch在JavaScript里是原生的,足以滿足項目需求。如果沒有特殊需求,我認為Fetch就是最合適的選擇。
留言點贊關注
我們一起分享AI學習與發展的干貨
如轉載,請后臺留言,遵守轉載規范
TML 實例
<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>菜鳥教程(runoob.com)</title></head><body><h1>我的第一個標題</h1><p>我的第一個段落。</p></body></html>
實例解析
DOCTYPE 聲明了文檔類型
位于標簽 <html> 與 </html> 描述了文檔類型
位于標簽 <body> 與 </body> 為可視化網頁內容
位于標簽 <h1> 與 </h1> 作為一個標題使用
位于標簽 <p> 與 </p> 作為一個段落顯示
<!DOCTYPE html> 在HTML5中也是描述了文檔類型。 |
什么是HTML?
HTML 是用來描述網頁的一種語言。
HTML 指的是超文本標記語言: HyperText Markup Language
HTML 不是一種編程語言,而是一種標記語言
標記語言是一套標記標簽 (markup tag)
HTML 使用標記標簽來描述網頁
HTML 文檔包含了HTML 標簽及文本內容
HTML文檔也叫做 web 頁面
HTML 標簽
HTML 標記標簽通常被稱為 HTML 標簽 (HTML tag)。
HTML 標簽是由尖括號包圍的關鍵詞,比如 <html>
HTML 標簽通常是成對出現的,比如 <b> 和 </b>
標簽對中的第一個標簽是開始標簽,第二個標簽是結束標簽
開始和結束標簽也被稱為開放標簽和閉合標簽
<標簽>內容</標簽>
HTML 元素
"HTML 標簽" 和 "HTML 元素" 通常都是描述同樣的意思.
但是嚴格來講, 一個 HTML 元素包含了開始標簽與結束標簽,如下實例:
HTML 元素:
<p>這是一個段落。</p>
Web 瀏覽器
Web瀏覽器(如谷歌瀏覽器,Internet Explorer,Firefox,Safari)是用于讀取HTML文件,并將其作為網頁顯示。
瀏覽器并不是直接顯示的HTML標簽,但可以使用標簽來決定如何展現HTML頁面的內容給用戶:
HTML 網頁結構
下面是一個可視化的HTML頁面結構:
<html>
<head>
<title>頁面標題</title>
</head>
<body>
<h1>這是一個標題</h1>
<p>這是一個段落。</p>
<p>這是另外一個段落。</p>
</body>
</html>
只有 <body> 區域 (白色部分) 才會在瀏覽器中顯示。 |
HTML版本
從初期的網絡誕生后,已經出現了許多HTML版本:
版本 | 發布時間 |
---|---|
HTML | 1991 |
HTML+ | 1993 |
HTML 2.0 | 1995 |
HTML 3.2 | 1997 |
HTML 4.01 | 1999 |
XHTML 1.0 | 2000 |
HTML5 | 2012 |
XHTML5 | 2013 |
<!DOCTYPE> 聲明
<!DOCTYPE>聲明有助于瀏覽器中正確顯示網頁。
網絡上有很多不同的文件,如果能夠正確聲明HTML的版本,瀏覽器就能正確顯示網頁內容。
doctype 聲明是不區分大小寫的,以下方式均可:
<!DOCTYPE html>
<!DOCTYPE HTML>
<!doctype html>
<!Doctype Html>
通用聲明
HTML5
<!DOCTYPE html>
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
XHTML 1.0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
查看完整網頁聲明類型 DOCTYPE 參考手冊。
中文編碼
目前在大部分瀏覽器中,直接輸出中文會出現中文亂碼的情況,這時候我們就需要在頭部將字符聲明為 UTF-8。
HTML 實例
<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>頁面標題</title></head><body><h1>我的第一個標題</h1><p>我的第一個段落。</p></body></html>
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。