Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions examples/FileStreaming.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* This is an example of streaming files */

const uWS = require('../dist/uws.js');
const fs = require('fs');
const port = 9001;

/* Small file is cached in memory */
const smallFileType = 'application/json';
const smallFileName = 'absolutPathTo/smallFile.json';
const smallFileCachedBuffer = fs.readFileSync(smallFileName);
console.log('Small file size is: '+ smallFileCachedBuffer.length +' bytes');

/* Big file is streamed from storage */
const bigFileType = 'video/mpeg';
const bigFileName = 'absolutPathTo/bigFile.mp3';
const bigFileSize = fs.statSync(bigFileName).size;
console.log('Big file size is: '+ bigFileSize +' bytes');

let lastStreamIndex = 0;
let openStreams = 0;

/* Helper function to stream data */
/** @param {import('node:Stream').Readable} readStream */
const streamData = (res, readStream, totalSize, onSucceed) => {
let chunkBuffer; /* Actual chunk being streamed */
let totalOffset = 0; /* Actual chunk offset */

/* Function to send actual chunk */
const sendChunkBuffer = () => {
const [ok, done] = res.tryEnd(chunkBuffer, totalSize);
if (done) {
/* Streaming finished */
readStream.destroy();
onSucceed();
} else if (ok) {
/* Chunk send succeed */
totalOffset += chunkBuffer.length;
} else {
/* Chunk send failed (client backpressure)
* onWritable will be called once client ready to receive new chunk
* Pause stream to wait client */
readStream.pause();
}
return ok;
};

/* Register onWritable callback
* Will be called to drain client backpressure */
res.onWritable((offset) => {
if (offset !== totalOffset) {
/* If start of the chunk was successfully sent
* We only send the missing part */
chunkBuffer = chunkBuffer.subarray(offset - totalOffset);
totalOffset = offset;
}
if (sendChunkBuffer()) {
/* Resume stream if resend succeed */
readStream.resume();
return true;
}
return false;
});

/* Register callback for stream events */
readStream.on('error', (err) => {
console.log('Error reading file: '+ err);
/* res.close() calls onAborted callback */
res.close();
}).on('data', (newChunkBuffer) => {
chunkBuffer = newChunkBuffer;
/* Cork before sending new chunk */
res.cork(sendChunkBuffer);
});
};

const app = uWS./*SSL*/App({
key_file_name: 'misc/key.pem',
cert_file_name: 'misc/cert.pem',
passphrase: '1234'
}).get('/smallFile', (res, req) => {
res.writeHeader('Content-Type', smallFileType);
/* !! Use this only for small-sized bodies !!
* May cause server backpressure and bad performance
* For large bodies you must use the streaming method */
res.end(smallFileCachedBuffer);
}).get('/bigFile', (res, req) => {
const streamIndex = ++ lastStreamIndex;
console.log('Stream ('+ streamIndex +') was opened, openStreams: '+ (++ openStreams));
const readStream = fs.createReadStream(bigFileName);
/* Attach onAborted handler because streaming is async */
res.onAborted(() => {
readStream.destroy();
console.log('Stream ('+ streamIndex +') failed, openStreams: '+ (-- openStreams));
});
res.writeHeader('Content-Type', bigFileType);
streamData(res, readStream, bigFileSize, () => {
console.log('Stream ('+ streamIndex +') succeed, openStreams: '+ (-- openStreams));
});
}).listen(port, (token) => {
if (token) {
console.log('Listening to port ' + port);
} else {
console.log('Failed to listen to port ' + port);
}
});
72 changes: 0 additions & 72 deletions examples/JsonPost.js

This file was deleted.

56 changes: 56 additions & 0 deletions examples/ParseRequestBody.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* This is an example of parsing request body */

const uWS = require('../dist/uws.js');
const port = 9001;

/* Helper function to parse JSON body */
const parseJSONBody = (res, callback) => {
let buffer;
/* Register data callback */
res.onData((ab, isLast) => {
const chunk = Buffer.from(ab);
if (isLast) {
let json;
try {
json = JSON.parse(buffer ? Buffer.concat([buffer, chunk]) : chunk);
} catch (e) {
json = undefined;
}
callback(json);
} else if (buffer) {
buffer = Buffer.concat([buffer, chunk]);
} else {
buffer = Buffer.concat([chunk]);
}
});
};

const app = uWS./*SSL*/App({
key_file_name: 'misc/key.pem',
cert_file_name: 'misc/cert.pem',
passphrase: '1234'
}).get('/jsonAPI', (res, req) => {
/* Attach onAborted handler because body parsing is async */
res.onAborted(() => {
console.log('Request aborted!');
});
parseJSONBody(res, (parsedJson) => {
if (parsedJson !== undefined) {
console.log('Valid JSON:', parsedJson);
res.cork(() => {
res.end('Thanks for your data!');
});
} else {
console.log('Invalid JSON or no data at all!');
res.cork(() => {
res.writeStatus('400 Bad Request').end();
});
}
});
}).listen(port, (token) => {
if (token) {
console.log('Listening to port ' + port);
} else {
console.log('Failed to listen to port ' + port);
}
});
115 changes: 0 additions & 115 deletions examples/VideoStreamer.js

This file was deleted.

42 changes: 0 additions & 42 deletions examples/VideoStreamerSync.js

This file was deleted.