diff --git a/dev/Remote/AbstractFetch.js b/dev/Remote/AbstractFetch.js index d0766b863..d5b375289 100644 --- a/dev/Remote/AbstractFetch.js +++ b/dev/Remote/AbstractFetch.js @@ -78,6 +78,45 @@ export class AbstractFetchRemote return this; } + /** + * Allows quicker visual responses to the user. + * Can be used to stream lines of json encoded data, but does not work on all servers. + * Apache needs 'flushpackets' like in + */ + streamPerLine(fCallback, sGetAdd) { + rl.fetch(getURL(sGetAdd)) + .then(response => response.body) + .then(body => { + // Firefox TextDecoderStream is not defined + // const reader = body.pipeThrough(new TextDecoderStream()).getReader(); + const reader = body.getReader(), + re = /\r\n|\n|\r/gm, + utf8decoder = new TextDecoder(); + let buffer = ''; + function processText({ done, value }) { + buffer += value ? utf8decoder.decode(value, {stream: true}) : ''; + for (;;) { + let result = re.exec(buffer); + if (!result) { + if (done) { + break; + } + reader.read().then(processText); + return; + } + fCallback(buffer.substring(0, result.index)); + buffer = buffer.substring(result.index + 1); + re.lastIndex = 0; + } + if (buffer.length) { + // last line didn't end in a newline char + fCallback(buffer); + } + } + reader.read().then(processText); + }) + } + /** * @param {?Function} fCallback * @param {string} sAction diff --git a/dev/bootstrap.js b/dev/bootstrap.js index a6ce988d7..36fa2c05a 100644 --- a/dev/bootstrap.js +++ b/dev/bootstrap.js @@ -55,7 +55,7 @@ export default App => { } }; - rl.fetchJSON = (resource, init, postData) => { + rl.fetch = (resource, init, postData) => { init = Object.assign({ mode: 'same-origin', cache: 'no-cache', @@ -64,7 +64,6 @@ export default App => { credentials: 'same-origin', headers: {} }, init); - init.headers.Accept = 'application/json'; if (postData) { init.method = 'POST'; init.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; @@ -86,7 +85,13 @@ export default App => { init.body = new URLSearchParams(postData); } - return fetch(resource, init).then(response => { + return fetch(resource, init); + }; + + rl.fetchJSON = (resource, init, postData) => { + init = Object.assign({ headers: {} }, init); + init.headers.Accept = 'application/json'; + return rl.fetch(resource, init, postData).then(response => { if (!response.ok) { return Promise.reject('Network response error: ' + response.status); } diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/http/stream.php b/snappymail/v/0.0.0/app/libraries/snappymail/http/stream.php new file mode 100644 index 000000000..49dbee134 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/snappymail/http/stream.php @@ -0,0 +1,48 @@ + + // We can't control them here + // We can control ending the response with \fastcgi_finish_request() + + if (!$binary) { + \header('Content-Type: text/plain'); + } + } + + public static function JSON($data) + { + echo \MailSo\Base\Utils::Php2js($data) . "\n"; + \ob_flush(); + \flush(); + } +}