網頁與伺服器的溝通


Posted by tzutzu858 on 2020-08-19

client 與 Server 怎麼做溝通?

  • response .html 檔案回來 :
    當按下重新整理時背後發生什麼事情,瀏覽器幫我們發一個 request 到這個頁面的網址,然後回傳 response 就是我們看到的這個頁面,瀏覽器把它 render 出來。

  • response JSON 格式檔案回來 :


用 node.js 呼叫 API 與在網頁上呼叫的根本差異是什麼?



傳送資料

第一種方式:表單 form

缺點是每次換資料都要換頁

<form method='GET' action='https://google.com'>
username: <input name='username'/>
<input type='submit'/>
</form>

第二種方式:ajax

不換頁也能跟 Server 溝通,Server 會回傳 response 給 javascript
AJAX ( Asynchronous JavaScript and XML ) 非同步的 JavaScript 與 XML 技術
早期都是用 XML 做為資料格式,現在比較多都用 JSON 格式,但還是叫 ajax,沒有問題。
Huli 文章回顧 跟著小明一起搞懂技術名詞:MVC、SPA 與 SSR

<script>
const request = new XMLHttpRequest()
request.onload = function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('err')
    }
}
request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
</script>
  • XMLHttpRequest() 是瀏覽器提供的 class
  • 放一個 function 到 onload 上面,當 request 拿到結果就會觸發 onload 事件,這樣的寫法就像之前寫的

    btn.addEventListener('click', function()...)
    // 某種程度也像 btn.onClick = function()... 只是沒辦法這樣用
    
  • open() 就是你要發 request 到這個地方
    第一個參數 : 用 GET 這個 method
    第二個參數 : 發到 google.com
    第三個參數 : 要不要非同步
    (感覺會用到同步只有網頁結帳的時候,這邊不確定)

  • request.send() : 才會真的把 request 傳出去

  • XMLHttpRequest.setRequestHeader()
    設定 HTTP 請求標頭(request header)值。setRequestHeader() 可被呼叫的時間點必須於 open() 之後、在 send() 之前。
    XMLHttpRequest

XMLHttpRequest

上下兩段程式碼意思是一樣的

const request = new XMLHttpRequest()
request.onload = function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('request.status,request.responseText')
    }
}

request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
const request = new XMLHttpRequest()
request.addEventListener('load', function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('request.status,request.responseText')
    }
})
request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
  • 從 Network 真的有發一個到 https://reqres.in/api/users 這裡,也有 response 回來,但要記住它是純文字所以要字的用 JSON.parse 把它變成 JSON 才能做一些事情。
  • 另外並不是所有的 response 都有 responseText

Same origin policy 與跨網域問題

當送 request 給 google 時,收到一個 response
顯示 :

Access to XMLHttpRequest at 'https://google.com' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requestes resource.

簡單來說就是 response header 沒有 'Access-Control-Allow-Origin' 這個東西,所以我們不能存取他,這是為什麼呢 ? 首先瀏覽器有個政策叫做 Same-origin policy 同源政策

所謂同源是指兩份網頁具備相同協定、埠號 (如果有指定) 以及主機位置

所以瀏覽器會預設不同源會把你擋掉,而被擋掉的解法 :
跨來源資源共用(CORS)

跨來源資源共用(Cross-Origin Resource Sharing (CORS))是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理取得存取其他來源(網域)伺服器特定資源權限的機制。當使用者代理請求一個不是目前文件來源——例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。

因此當 server 沒有在 response headers 上加 Access-Control-Allow-Origin 你是絕對沒有辦法拿到 response 的,沒有任何方法繞過這個限制,所以要馬是同來源,要馬 server 在 response headers 有加 Access-Control-Allow-Origin
那為什麼要有這個限制,最主要的原因是安全性,而這些限制都是瀏覽器加上的,所以一旦脫離瀏覽器,例如在 node.js 上跑,就不會有這些限制。

補充文章 : 輕鬆理解 Ajax 與跨來源請求


第三種方式:JSONP

但現在很少人在用,全名 JSON with padding

有些標籤不受到同源政策影響 :

  1. 圖片 : 就算跨來源的圖片一樣可以載入,因為圖片沒有安全性的問題
  2. <script src="可以引入其他 domain 的 js 進來"> 為了方便

所以就有人利用 script 這個標籤來拿到資料
比如說 load 一個 script ,那他回傳的內容可以是一個 function ,裡面夾帶他真正要回傳的資料


還有比較新的傳資料方式 : Fetch API


單向傳送資料的延伸應用(email 或廣告商的追蹤)

有時候你只想要傳一些資料回去,你不想拿到 response ,例如,發一個 email ,追蹤多少人打開過他
作法 : 在 email 放了又小又透明的圖片,圖片的 src 是一個網址,一旦打開信件後,你的信件軟體或是 gmail 就會下載那張透明的圖片去顯示出來,所以就會發一個 request 到網址去,server 端就知道有人打開這個網址,就代表有人打開這封信。










Related Posts

PDIS 實習日誌:神啊!請賜給我完美陌生人

PDIS 實習日誌:神啊!請賜給我完美陌生人

用 Python 自學程式設計:程式設計思維入門

用 Python 自學程式設計:程式設計思維入門

七天學會 swift - NSPredicate Day4

七天學會 swift - NSPredicate Day4


Comments