iT邦幫忙

0

請問 http response 的問題

請教各位大大:
我用 Node.JS寫了一個 http server:

const http = require('http');
const pid = process.pid;
let url;

http.createServer((req, res) => {
  url = req.url;
  console.log(`request from ${url}`);
  res.end(`Hello`);
}).listen(8080, () => {
  console.log(`Started`);
});

用瀏覽器 http://localhost:8080/ 沒有問題,可以看到 Hello在網頁上。

在 html用 javascript寫:

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
  <script>
    fetch('http://localhost:8080/',{mode: 'no-cors'})
        .then(res => console.log(res))
  </script>
</body>

</html>

要如何抓到這個 Hello呢?

看更多先前的討論...收起先前的討論...
淺水員 iT邦大師 6 級 ‧ 2020-08-20 12:04:17 檢舉
.then(res=>res.text()).then(txt=>console.log(txt))
Amigo iT邦新手 5 級 ‧ 2020-08-20 13:14:56 檢舉
我試過了,也抓不到
fillano iT邦超人 1 級 ‧ 2020-08-20 13:19:03 檢舉
瀏覽器有什麼訊息?開發人員工具=>網路 看到什麼?
因為你用 end 不是應該用 send ?
fillano iT邦超人 1 級 ‧ 2020-08-20 13:51:09 檢舉
用end沒問題啦。你的html在哪裡?
我後來有發現用 axios 都抓得到用 fetch 抓不到XD
fillano iT邦超人 1 級 ‧ 2020-08-20 13:56:49 檢舉
把mode改成cors,然後node.js送出Access-Control-Allow-Origin:*標頭試試看。
Amigo iT邦新手 5 級 ‧ 2020-08-20 14:06:36 檢舉
開發人員工具=>網路 response 有 hello
Amigo iT邦新手 5 級 ‧ 2020-08-20 14:08:08 檢舉
Request URL: http://localhost:8080/
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade
Connection: keep-alive
Content-Length: 5
Date: Thu, 20 Aug 2020 05:58:36 GMT
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: localhost:8080
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
看了費大的回覆去 google 了 fetch 的 mode: 'no-cors'
發現 no-cors 是不錯的東西但不熟的話也是一個坑...
fillano iT邦超人 1 級 ‧ 2020-08-20 15:08:32 檢舉
Sec-Fetch-Site: cross-site...所以fetch的html跟node.js伺服器不是同一個site?
Amigo iT邦新手 5 級 ‧ 2020-08-20 16:23:00 檢舉
都在自己這一台PC,site是指目錄嗎?
Amigo iT邦新手 5 級 ‧ 2020-08-20 16:50:56 檢舉
(1)node.js 加 res.setHeader('Access-Control-Allow-Origin', '*');
(2)http 去掉no-cors
這樣可行。感謝fillano超人!
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

2
dragonH
iT邦超人 5 級 ‧ 2020-08-20 13:53:10

backend

const http = require('http');
const fs = require('fs');

const port = process.env.PORT || 3000;
let url = '';
http.createServer((req, res) => {
    ({ url } = req);
    console.log(`request from ${url}`);
    switch (url) {
        case '/': {
            const htmlFile = fs.readFileSync('./index.html', { encoding: 'utf-8'});
            res.writeHead(200,{'Content-Type':'text/html'});
            res.write(htmlFile);
            res.end();
            break;
        }
        case '/api': {
            res.writeHead(200,{'Content-Type':'text/html'});
            res.write('hello');
            res.end();
            break;
        }
    }
}).listen(port, () => {
    console.log(`Server is running on http://127.0.0.1:${port}`);
});

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script>
    fetch('http://127.0.0.1:3000/api')
        .then(res => res.text())
        .then(res => console.log(res))
  </script>
<body>
</body>
</html>

這樣

直接測你的code 會發現拿不到 response
image

看更多先前的回應...收起先前的回應...
fillano iT邦超人 1 級 ‧ 2020-08-20 14:24:53 檢舉

https://developer.mozilla.org/en-US/docs/Web/API/Response/type

response type 'opaque': Response for “no-cors” request to cross-origin resource.
fillano iT邦超人 1 級 ‧ 2020-08-20 14:51:06 檢舉

真正的原因被過濾掉了XD

dragonH iT邦超人 5 級 ‧ 2020-08-20 15:24:03 檢舉

/images/emoticon/emoticon32.gif

Amigo iT邦新手 5 級 ‧ 2020-08-20 16:28:01 檢舉

意思是不是說:server沒有開放,client不能用no-cors強取? 但 Chrome開發人員工具=>網路=>response 有 hello字樣,又表示其實資料有下來?

Amigo iT邦新手 5 級 ‧ 2020-08-20 17:05:39 檢舉

謝謝 dragonH超人的程式。抱歉我沒說清楚,我是直接用瀏覽器開啟.html,所以才有同源問題吧!

fillano iT邦超人 1 級 ‧ 2020-08-20 17:07:09 檢舉

我看了一下規格,mode用no-cors時,發生非網路錯誤的問題,在javascript端取得的response是過濾過的,以避免資訊洩露。我猜測就是一些header的條件不合之類,但是從javascript端看不出問題(被過濾成格式統一的response),然後開發工具會告訴你沒問題,因為這是內部request/response之後才處理的。

sec開頭那幾個是提供request上下文的標頭,應該是fetch自己送出去的。google一下就知道意思。

dragonH iT邦超人 5 級 ‧ 2020-08-20 17:09:55 檢舉

Amigo

跨域問題我記得不會你加了 no-cors

就能直接解決

必須要 backend server 配合才能

fillano iT邦超人 1 級 ‧ 2020-08-21 09:25:23 檢舉

我試過,以樓煮的例子,no-cors加上伺服器端送Access-Control-Allow-Origin: *標頭似乎也沒用。

no-cors只是不會跳錯誤,該攔該擋的瀏覽器都會做。直接開html,那跟localhost127.0.0.1就不是同樣site了,所以你會收到Sec-Fetch-Site: cross-site這個fetch發出來的標頭(這是使用者無法更改的標頭)。

猜測問題發生的原因:通常預設的安全規則是只能request同源(same-site)的資源,但是因為mode設為no-cors導致內部request/response成功,但還是被安全原則檔下,然後response又被過濾,所以看不到真正的錯誤。

細節要看一下fetch api的規格書會比較清楚,我只簡單瞄了一下。

Amigo iT邦新手 5 級 ‧ 2020-08-24 11:23:07 檢舉

謝謝 fillano超人!我找到
https://chrome.google.com/webstore/detail/cors-unblock/lfhmikememgdcahcdlaciloancbhjino
這工具可以開關chrome的CORS限制,但不知這是什麼樣的概念?用什麼技術做到的?

我要發表回答

立即登入回答