Note:
要做的事是透過前端從 serverA取資料,用 content-type FormData格式打包成一個 http post方式的 request送到 serverB。遇到的問題是,B無法讀取接收到的訊息。但在這之前也做過一樣方向的傳輸
Note:
只是傳輸的訊息格式不同,剛剛是傳FormData, 第一次是傳 application/json格式, B接收之後順利解讀。所以猜測是B的解讀方式有誤,從這個方向去debug
Note:
因此就沒有大腦的測試各種接收方式,結果都讀不到。
Note:
卡了一個上午想不到還可以怎麼做,於是開始求救
Note:
謝謝ES幫忙,ES從源頭,發送訊息的 serverA開始追蹤,並試著傳另一個已經確保可行的相同的content-type格式的訊息,很快地就發現問題。開啟瀏覽器開發介面的network tag,左邊是 serverB不能解析的訊息,右邊是可以解析的,可以看到上方兩個紅色框的差別是右邊有 boundary字串;下方結果的差別是右邊有 view parsed的 tab選項。 然後就很驚訝原來一開始 serverA打包訊息的方式就不對了。
Note:
用於指示資源的媒體類型。在request中, 用在client告訴 server他傳送的訊息是什麼類型的data。在respose中則反之。
Multipurpose Internet Mail Extensions (MIME)
是一種Internet標準,它擴展了電子郵件的格式以支持
雖然MIME主要是為SMTP設計的 但MIME標准定義的內容類型在電子郵件之外的通信協議中也很重要,例如HTTP。 服務器在任何Web傳輸的開頭插入MIME頭。
multipart
Note:
這邊是幾個常見的類型/次類型。 我們這次遇到的問題格式是multipart。顧名思義就是data有很多個part,可能很大。當文件太長,HTTP無法在一個包之內發送完畢,就需要分割數據,分割成一個一個塊發送給服務端。
Note:
為了一個一個塊發送給服務端,multipart需要有 boundary來區分每一塊。
Note:
對於 multipart entities,需要使用邊界指令,該指令由已知通過電子郵件網關非常 robust一組字符中的1到70個字符組成,並且不以空格結尾。 它用於封裝message的多個部分的邊界。 通常,header邊界前面有兩個破折號,最後的邊界在末尾附加了兩個破折號。
request.form.get('path',False)
request.form['path']
f = request.form
for key in f.keys():
for value in f.getlist(key):
print(key,":",value)
request.get_json() recv: {'encodedData': 'testjson'}
request.json recv: {'encodedData': 'testjson'}
request.data recv: b'{"encodedData":"testjson"}' #bytes, need "json.loads()"
var data = {
name: 'theKey',
surname: 'theValue'
};
var boundary = String(Math.random()).slice(2);
var boundaryMiddle = '--' + boundary + '\r\n';
var boundaryLast = '--' + boundary + '--\r\n'
var body = ['\r\n'];
for (var key in data) {
body.push('Content-Disposition: form-data; name="' + key + '"\r\n\r\n' + data[key] + '\r\n');
}
body = body.join(boundaryMiddle) + boundaryLast;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/test', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
xhr.onreadystatechange = function() {
if (this.readyState != 4) return;
alert( this.responseText );
}
xhr.send(body);
var FD = new FormData();
var xhr = new XMLHttpRequest();
xhr.open('POST', '/test', true);
xhr.send(FD);
確保傳到後端是自己想像的格式
舉例: 如果要傳 json物件xhr.send(JSON.stringify({"t1":"t1data"}));
只能用 request.data取出 bytes字串
request.get_json() recv: {'encodedData': 'testjson'}
request.json recv: {'encodedData': 'testjson'}
request.data recv: b'{"encodedData":"testjson"}'
Note:
在前端先印出來看,發現前端讀到的data就已經不是預想的類型了。serverA送出的是 base64轉換過的 bytes obj,原本以為前端收到後可以直接轉傳…看來案情並不單純
Javascript中的 Buffers和 Views
Note:
謝謝Chris幫忙,請教chris後了解, javascipt會將 data存放在 buffer,然後用不同的views去解讀,會讀出不同的東西。因為解讀的長度單位不同,像是 base64的 bytes obj 就要用1個 byte的單位去解讀,出來才是我們要的資料
var origin_string = String.fromCharCode.apply(null, new Uint8Array(data));