Chapter 4: initial recipe samples

This commit is contained in:
Beth Griggs 2020-04-29 22:00:34 +01:00
parent 503edc4ec2
commit bcf782f7dc
No known key found for this signature in database
GPG Key ID: D7062848A1AB005C
59 changed files with 471 additions and 655 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/.DS_Store

View File

@ -1,19 +0,0 @@
'use strict'
const from = require('from2')
const to = require('to2')
const duplexify = require('duplexify')
const rs = from(() => {
rs.push(Buffer.from('Hello, World!'))
rs.push(null)
})
const ws = to((data, enc, cb) => {
console.log(`Data written: ${data.toString()}`)
cb()
})
const stream = duplexify(ws, rs)
stream.pipe(stream)

View File

@ -1,16 +0,0 @@
{
"name": "composing-duplex-streams",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"from2": "^2.3.0",
"to2": "^1.0.0"
}
}

View File

@ -1,19 +0,0 @@
'use strict'
const { Readable, Writable } = require('readable-stream')
const rs = Readable({
read: () => {
rs.push(Buffer.from('Hello, World!'))
rs.push(null)
}
})
const ws = Writable({
write: (data, enc, cb) => {
console.log(`Data written: ${data.toString()}`)
cb()
}
})
rs.pipe(ws)

View File

@ -1,20 +0,0 @@
'use strict'
const from = require('from2')
const to = require('to2')
const rs = from(() => {
rs.push(Buffer.from('Hello, World!'))
rs.push(null)
})
// rs.on('data', (data) => {
// console.log(data.toString())
// })
const ws = to((data, enc, cb) => {
console.log(`Data written: ${data.toString()}`)
cb()
})
rs.pipe(ws)

View File

@ -1,16 +0,0 @@
{
"name": "from2-to2-streams",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"from2": "^2.3.0",
"to2": "^1.0.0"
}
}

View File

@ -1,16 +0,0 @@
'use strict'
const from = require('from2')
const rs = from((size, cb) => {
setTimeout(() => {
rs.push('Data 0')
setTimeout(() => {
rs.push('Data 1')
cb()
}, 50)
}, 100)
})
rs.on('data', (data) => {
console.log(data.toString())
})

View File

@ -1,16 +0,0 @@
{
"name": "readable-flow-control",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"from2": "^2.3.0",
"readable-stream": "^2.2.6"
}
}

View File

@ -1,18 +0,0 @@
'use strict'
// WARNING: DOES NOT WORK AS EXPECTED
const { Readable } = require('readable-stream')
const rs = Readable({
read: () => {
setTimeout(() => {
rs.push('Data 0')
setTimeout(() => {
rs.push('Data 1')
}, 50)
}, 100)
}
})
rs.on('data', (data) => {
console.log(data.toString())
})

View File

@ -1,13 +0,0 @@
'use strict'
const { Transform } = require('readable-stream')
class MyTransform extends Transform {
_transform (chunk, enc, cb) {
cb(null, chunk.toString().toUpperCase())
}
}
const upper = new MyTransform()
process.stdin.pipe(upper).pipe(process.stdout)

View File

@ -1,11 +0,0 @@
'use strict'
const { Transform } = require('readable-stream')
const upper = Transform({
transform: (chunk, enc, cb) => {
cb(null, chunk.toString().toUpperCase())
}
})
process.stdin.pipe(upper).pipe(process.stdout)

View File

@ -1,12 +0,0 @@
{
"name": "core-transform-streams",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

View File

@ -1,18 +0,0 @@
'use strict'
const stream = require('readable-stream')
const util = require('util')
function MyTransform(opts) {
stream.Transform.call(this, opts)
}
util.inherits(MyTransform, stream.Transform)
MyTransform.prototype._transform = function (chunk, enc, cb) {
cb(null, chunk.toString().toUpperCase())
}
const upper = new MyTransform()
process.stdin.pipe(upper).pipe(process.stdout)

View File

@ -1,15 +0,0 @@
'use strict'
const { Transform } = require('readable-stream')
const { serialize } = require('ndjson')
const xyz = Transform({
objectMode: true,
transform: ({x, y}, enc, cb) => { cb(null, {z: x + y}) }
})
xyz.pipe(serialize()).pipe(process.stdout)
xyz.write({x: 199, y: 3})
xyz.write({x: 10, y: 12})

View File

@ -1,14 +0,0 @@
'use strict'
const through = require('through2')
const { serialize } = require('ndjson')
const xyz = through.obj(({x, y}, enc, cb) => {
cb(null, {z: x + y})
})
xyz.pipe(serialize()).pipe(process.stdout)
xyz.write({x: 199, y: 3})
xyz.write({x: 10, y: 12})

View File

@ -1,17 +0,0 @@
{
"name": "object-streams",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"ndjson": "^1.5.0",
"readable-stream": "^2.2.6",
"through2": "^2.0.3"
}
}

View File

@ -1,9 +0,0 @@
'use strict'
const through = require('through2')
const upper = through((chunk, enc, cb) => {
cb(null, chunk.toString().toUpperCase())
})
process.stdin.pipe(upper).pipe(process.stdout)

View File

@ -1,15 +0,0 @@
{
"name": "through-streams",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"through2": "^2.0.3"
}
}

View File

@ -1,22 +0,0 @@
'use strict'
const { Readable, Writable } = require('readable-stream')
var i = 20
const rs = Readable({
read: (size) => {
setImmediate(function () {
rs.push(i-- ? Buffer.alloc(size) : null)
})
}
})
const ws = Writable({
write: (chunk, enc, cb) => {
console.log(ws._writableState.length)
setTimeout(cb, 1)
}
})
rs.pipe(ws)

View File

@ -1,22 +0,0 @@
'use strict'
const { Readable, Writable } = require('readable-stream')
var i = 20
const rs = Readable({
read: (size) => {
setImmediate(function () {
rs.push(i-- ? Buffer.alloc(size) : null)
})
}
})
const ws = Writable({
write: (chunk, enc, cb) => {
console.log(ws._writableState.length)
setTimeout(cb, 1)
}
})
rs.on('data', (chunk) => ws.write(chunk))

View File

@ -1,40 +0,0 @@
'use strict'
const { Readable, Writable } = require('readable-stream')
var i = 20
const rs = Readable({
read: (size, cb) => {
setImmediate(function () {
rs.push(i-- ? Buffer.alloc(size) : null)
})
}
})
const ws = Writable({
write: (chunk, enc, cb) => {
console.log(ws._writableState.length)
setTimeout(cb, 1)
}
})
function write (chunk, cb) {
const writable = ws.write(chunk)
if (writable === false) {
ws.once('drain', cb)
return
}
process.nextTick(cb)
}
function read () {
const chunk = rs.read()
if (chunk === null) {
rs.once('readable', read)
return
}
write(chunk, read)
}
rs.once('readable', read)

View File

@ -1,28 +0,0 @@
'use strict'
const { Readable, Writable } = require('readable-stream')
var i = 20
const rs = Readable({
read: (size) => {
setImmediate(function () {
rs.push(i-- ? Buffer.alloc(size) : null)
})
}
})
const ws = Writable({
write: (chunk, enc, cb) => {
console.log(ws._writableState.length)
setTimeout(cb, 1)
}
})
rs.on('data', (chunk) => {
const writable = ws.write(chunk)
if (writable === false) {
rs.pause()
ws.once('drain', () => rs.resume())
}
})

View File

@ -1,22 +0,0 @@
'use strict'
const through = require('through2')
const split = require('split2')
const pumpify = require('pumpify')
function pingProtocol() {
const ping = /Ping:\s+(.*)/
const protocol = through(each)
function each (line, enc, cb) {
if (ping.test(line)) {
cb(null, `Pong: ${line.toString().match(ping)[1]}\n`)
return
}
cb(null, 'Not Implemented\n')
}
return pumpify(split(), protocol)
}
module.exports = pingProtocol

View File

@ -1,17 +0,0 @@
{
"name": "foo-protocol-stream",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pumpify": "^1.3.5",
"split2": "^2.1.1",
"through2": "^2.0.3"
}
}

View File

@ -1,25 +0,0 @@
'use strict'
var from = require('from2')
function createInfiniteTickStream () {
var tick = 0
return from.obj((size, cb) => {
setImmediate(() => cb(null, {tick: tick++}))
})
}
var stream = createInfiniteTickStream()
stream.on('data', (data) => {
console.log(data)
})
stream.on('close', () => {
console.log('(stream destroyed)')
})
setTimeout(() => {
stream.destroy()
}, 1000)

View File

@ -1,15 +0,0 @@
{
"name": "stream-destruction",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"from2": "^2.3.0"
}
}

View File

@ -1,17 +0,0 @@
'use strict'
const net = require('net')
const pump = require('pump')
const ping = require('../ping-protocol-stream')
const server = net.createServer((socket) => {
const protocol = ping()
pump(socket, protocol, socket, closed)
})
function closed (err) {
if (err) console.error('connection closed with error', err)
else console.log('connection closed')
}
server.listen(3000)

View File

@ -1,15 +0,0 @@
{
"name": "tcp-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pump": "^1.0.2"
}
}

13
Chapter04/file-upload/package-lock.json generated Normal file
View File

@ -0,0 +1,13 @@
{
"name": "file-upload",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"formidable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
}
}
}

View File

@ -0,0 +1,16 @@
{
"name": "file-upload",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"formidable": "^1.2.2"
}
}

View File

@ -0,0 +1,5 @@
<form method="POST" enctype="multipart/form-data">
<label for="userfile">File:</label>
<input type="file" id="userfile" name="userfile"><br>
<input type="submit">
</form>

View File

@ -0,0 +1,55 @@
const fs = require('fs')
const http = require('http')
const path = require('path')
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html'))
const formidable = require('formidable')
http.createServer((req, res) => {
if (req.method === 'GET') {
get(res)
return
}
if (req.method === 'POST') {
post(req, res)
return
}
error(405, res)
}).listen(3000)
function get(res) {
res.writeHead(200, {
'Content-Type': 'text/html'
})
res.end(form)
}
function post(req, res) {
if (!/multipart\/form-data/.test(req.headers['content-type'])) {
error(415, res)
return
}
const form = formidable({
multiples: true,
uploadDir: './uploads'
});
form.parse(req, (err, fields, files) => {
if (err) return err
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
fields,
files
}))
})
}
function error(code, res) {
res.statusCode = code
res.end(http.STATUS_CODES[code])
}

View File

@ -0,0 +1,28 @@
const http = require('http')
const HOSTNAME = process.env.HOSTNAME || '0.0.0.0'
const PORT = process.env.PORT || 8080
const server = http.createServer((req, res) => {
if (req.method !== 'GET') return error(res, 405)
if (req.url === '/todo') return todo(res)
if (req.url === '/') return index(res)
error(res, 404)
});
function error(res, code) {
res.statusCode = code
res.end(`{"error": "${http.STATUS_CODES[code]}"}`)
}
function todo(res) {
res.end('[{"task_id": 1, "description": "walk dog"}]}')
}
function index(res) {
res.end('{"name": "todo-server"}')
}
server.listen(PORT, HOSTNAME, () => {
console.log('Server listening on', server.address())
})

View File

@ -0,0 +1,28 @@
const https = require('https')
// http.get('http://example.com', (res) => res.pipe(process.stdout))
const payload = `{
"name": "Beth",
"job": "Software Engineer"
}`
const opts = {
method: 'POST',
hostname: 'postman-echo.com',
path: '/post',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload)
}
}
const req = https.request(opts, (res) => {
process.stdout.write('Status Code: ' + res.statusCode + '\n')
process.stdout.write('Body: ')
res.pipe(process.stdout)
})
req.on('error', (err) => console.error('Error: ', err))
req.end(payload)

View File

@ -1,19 +0,0 @@
'use strict'
const fs = require('fs')
const http = require('http')
const pump = require('pump')
const server = http.createServer((req, res) => {
const stream = fs.createReadStream('big.file')
pump(stream, res, done)
})
function done (err) {
if (err) {
return console.error('File was not fully streamed to the user', err)
}
console.log('File was fully streamed to the user')
}
server.listen(3000)

View File

@ -1,15 +0,0 @@
{
"name": "big-file-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pump": "^1.0.2"
}
}

View File

@ -1,25 +0,0 @@
'use strict'
const { createGzip } = require('zlib')
const { createCipher } = require('crypto')
const pumpify = require('pumpify')
const base64 = require('base64-encode-stream')
function pipeline () {
const stream1 = createGzip()
const stream2 = createCipher('aes192', 'secretz')
const stream3 = base64()
return pumpify(stream1, stream2, stream3)
}
const pipe = pipeline()
pipe.end('written to stream1')
pipe.on('data', (data) => {
console.log('stream3 says: ', data.toString())
})
pipe.on('finish', () => {
console.log('all data was successfully flushed to stream3')
})

View File

@ -1,16 +0,0 @@
{
"name": "pumpified-pipeline",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"base64-encode-stream": "^1.0.0",
"pumpify": "^1.3.5"
}
}

View File

@ -0,0 +1,56 @@
const http = require('http')
const fs = require('fs')
const path = require('path')
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html'))
http.createServer((req, res) => {
if (req.method === 'GET') {
get(res)
return
}
if (req.method === 'POST') {
post(req, res)
return
}
error(405, res)
}).listen(3000)
function get(res) {
res.writeHead(200, {
'Content-Type': 'text/html'
})
res.end(form)
}
function post(req, res) {
if (req.headers['content-type'] !== 'application/json') {
error(415, res)
return
}
let input = '';
req.on('data', chunk => {
input += chunk.toString()
})
req.on('end', () => {
const parsed = JSON.parse(input)
if (parsed.err) {
error(400, 'Bad Request', res)
return
}
console.log('Received data: ', parsed)
res.end('{"data": ' + input + "}")
})
}
function error(code, res) {
res.statusCode = code
res.end(http.STATUS_CODES[code])
}

View File

@ -0,0 +1,30 @@
<form method="POST">
<label for="forename">Forename:</label>
<input id="forename" name="forename">
<label for="surname">Surname:</label>
<input id="surname" name="surname">
<input type="submit" value="Submit">
</form>
<script>
document.forms[0].addEventListener('submit', (event) => {
event.preventDefault()
let data = {
'forename': document.getElementById('forename').value,
'surname': document.getElementById('surname').value
};
console.log('data', data);
fetch('http://localhost:3000', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(function (response) {
console.log(response);
return response.json();
});
});
</script>

View File

@ -0,0 +1,48 @@
const http = require('http')
const fs = require('fs')
const path = require('path')
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html'))
http.createServer((req, res) => {
if (req.method === 'GET') {
get(res)
return
}
if (req.method === 'POST') {
post(req, res)
return
}
error(405, res)
}).listen(3000)
function get(res) {
res.writeHead(200, {
'Content-Type': 'text/html'
})
res.end(form)
}
function post(req, res) {
if (req.headers['content-type'] !== 'application/x-www-form-urlencoded') {
error(415, res)
return
}
let input = '';
req.on('data', chunk => {
input += chunk.toString()
})
req.on('end', () => {
console.log(input);
res.end(http.STATUS_CODES[200])
})
}
function error(code, res) {
res.statusCode = code
res.end(http.STATUS_CODES[code])
}

View File

@ -1,9 +0,0 @@
'use strict'
const rs = fs.createReadStream('/dev/urandom')
var size = 0
rs.on('data', (data) => {
size += data.length
console.log('File size:', size)
})

View File

@ -1,17 +0,0 @@
'use strict'
const fs = require('fs')
const rs = fs.createReadStream(__filename)
rs.on('readable', () => {
var data = rs.read()
while (data !== null) {
console.log('Read chunk:', data)
data = rs.read()
}
})
rs.on('end', () => {
console.log('No more data')
})

View File

@ -1,12 +0,0 @@
'use strict'
const fs = require('fs')
const rs = fs.createReadStream(__filename)
rs.on('data', (data) => {
console.log('Read chunk:', data)
})
rs.on('end', () => {
console.log('No more data')
})

40
Chapter04/server-smtp/package-lock.json generated Normal file
View File

@ -0,0 +1,40 @@
{
"name": "server-smtp",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"base32.js": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz",
"integrity": "sha1-tYLexpPC8R6JPPBk7mrFthMaIgI="
},
"ipv6-normalize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz",
"integrity": "sha1-GzJYKQ02X6gyOeiZB93kWS52IKg="
},
"nodemailer": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz",
"integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA=="
},
"smtp-server": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.6.0.tgz",
"integrity": "sha512-DVEVWzL4s1GWzAs4+6rbhNZpAn61+V8l4b7R8zHLAW2jmlwKz9IKQmdgm5sNruCRnS01BYyitI98vJo7LDnXfg==",
"requires": {
"base32.js": "0.1.0",
"ipv6-normalize": "1.0.1",
"nodemailer": "6.4.5"
},
"dependencies": {
"nodemailer": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.5.tgz",
"integrity": "sha512-NH7aNVQyZLAvGr2+EOto7znvz+qJ02Cb/xpou98ApUt5tEAUSVUxhvHvgV/8I5dhjKTYqUw0nasoKzLNBJKrDQ=="
}
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"name": "server-smtp",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"nodemailer": "^6.4.6",
"smtp-server": "^3.6.0"
}
}

View File

@ -0,0 +1,18 @@
const nodemailer = require("nodemailer")
let transporter = nodemailer.createTransport({
host: "localhost",
port: 4321
})
transporter.sendMail({
from: 'beth@example.com',
to: 'laddie@example.com',
subject: "Hello",
text: "Hello world!"
}, (err, info) => {
if (err) {
console.log(err)
}
console.log("Message Sent:", info)
})

View File

@ -0,0 +1,14 @@
const SMTPServer = require("smtp-server").SMTPServer
const PORT = 4321
const server = new SMTPServer({
disabledCommands: ['STARTTLS', 'AUTH'],
logger: true
})
server.on('error', err => {
console.error(err);
})
server.listen(PORT)

View File

@ -1,10 +0,0 @@
const net = require('net')
const fs = require('fs')
net.createServer((socket) => {
const content = fs.createReadStream(__filename)
content.pipe(socket)
content.on('end', () => {
socket.end('\n======= Footer =======\n')
})
}).listen(3000)

View File

@ -1,10 +0,0 @@
const net = require('net')
const fs = require('fs')
net.createServer((socket) => {
const content = fs.createReadStream(__filename)
content.pipe(socket, {end: false})
content.on('end', () => {
socket.end('\n======= Footer =======\n')
})
}).listen(3000)

View File

@ -1,20 +0,0 @@
'use strict'
const zlib = require('zlib')
const map = require('tar-map-stream')
const decompress = zlib.createGunzip()
const whoami = process.env.USER || process.env.USERNAME
const convert = map((header) => {
header.uname = whoami
header.mtime = new Date()
header.name = header.name.replace('node-v0.1.100', 'edon-v0.0.0')
return header
})
const compress = zlib.createGzip()
process.stdin
.pipe(decompress)
.pipe(convert)
.pipe(compress)
.pipe(process.stdout)

View File

@ -1,15 +0,0 @@
{
"name": "piper",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"tar-map-stream": "^1.0.0"
}
}

View File

@ -0,0 +1,11 @@
const fs = require('fs')
const http = require('http')
const index = fs.readFileSync('public/index.html')
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html')
res.end(index)
})
server.listen(8080)

View File

@ -0,0 +1,18 @@
const WebSocket = require('ws')
const ws = new WebSocket('ws://localhost:3000')
ws.on('open', () => {
console.log('Connected')
})
ws.on('close', () => {
console.log('Disconnected')
})
ws.on('message', (message) => {
console.log('Received:', message)
})
setInterval(() => {
ws.send("Hello")
}, 3000)

View File

@ -0,0 +1,13 @@
{
"name": "ws-server",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ws": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
"integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
}
}
}

View File

@ -0,0 +1,16 @@
{
"name": "ws-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"ws": "^7.2.5"
}
}

View File

@ -0,0 +1,32 @@
<h1>Communicating with WebSockets</h1>
<input id="msg"><button id="send">Send</button>
<div id="output"></div>
<script>
const ws = new WebSocket('ws://localhost:3000')
const output = document.getElementById('output')
const send = document.getElementById('send')
send.addEventListener('click', () => {
const msg = document.getElementById('msg').value
ws.send(msg)
output.innerHTML += log('Sent', msg)
})
function log(event, msg) {
return '<p>' + event + ': ' + msg + '</p>'
}
ws.onmessage = function (e) {
output.innerHTML += log('Received', e.data)
}
ws.onclose = function (e) {
output.innerHTML += log('Disconnected', e.code)
}
ws.onerror = function (e) {
output.innerHTML += log('Error', e.data)
}
</script>

View File

@ -0,0 +1,12 @@
const WebSocket = require('ws')
const WebSocketServer = new WebSocket.Server({
port: 3000
})
WebSocketServer.on('connection', (socket) => {
socket.on('message', (msg) => {
console.log('Received:', msg)
if (msg === 'Hello') socket.send('World!')
})
})