Skip to content

Commit a65922f

Browse files
committed
Add HTTP API client-server binding
1 parent 507f14d commit a65922f

File tree

8 files changed

+206
-0
lines changed

8 files changed

+206
-0
lines changed

JavaScript/1-HTTP/api/move.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const move = (point, x, y) => {
2+
point.x += x;
3+
point.y += y;
4+
};
5+
6+
module.exports = async (name, x, y) => {
7+
const shape = memory.get(name);
8+
if (!shape) return 'Shape is not found';
9+
for (const key in shape) {
10+
const point = shape[key];
11+
move(point, x, y);
12+
}
13+
return 'Shape moved';
14+
};

JavaScript/1-HTTP/api/read.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = async name => {
2+
const shape = memory.get(name);
3+
if (!shape) return 'Shape is not found';
4+
return shape;
5+
};

JavaScript/1-HTTP/api/rect.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Point {
2+
constructor(x, y) {
3+
this.x = x;
4+
this.y = y;
5+
}
6+
}
7+
8+
class Rect {
9+
constructor(x1, y1, x2, y2) {
10+
this.a = new Point(x1, y1);
11+
this.b = new Point(x2, y1);
12+
this.c = new Point(x2, y2);
13+
this.d = new Point(x1, y2);
14+
}
15+
}
16+
17+
module.exports = async (name, x1, y1, x2, y2) => {
18+
const rect = new Rect(x1, y1, x2, y2);
19+
memory.set(name, rect);
20+
return 'ok';
21+
};

JavaScript/1-HTTP/api/render.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = async name => {
2+
const shape = memory.get(name);
3+
if (!shape) return 'Shape is not found';
4+
const points = [];
5+
for (const key in shape) {
6+
const point = shape[key];
7+
points.push(point);
8+
}
9+
const svg = [];
10+
svg.push('<svg viewBox="-20 -20 40 40" xmlns="http://www.w3.org/2000/svg">');
11+
svg.push('<polygon points="');
12+
svg.push(points.map(point => `${point.x},${point.y}`).join(' '));
13+
svg.push('" /></svg>');
14+
return svg.join('');
15+
};

JavaScript/1-HTTP/api/rotate.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const rotate = (point, angle) => {
2+
const sin = Math.sin(angle);
3+
const cos = Math.cos(angle);
4+
const { x, y } = point;
5+
point.x = x * cos - y * sin;
6+
point.y = x * sin + y * cos;
7+
};
8+
9+
module.exports = async (name, angle) => {
10+
const shape = memory.get(name);
11+
if (!shape) return 'Shape is not found';
12+
for (const key in shape) {
13+
const point = shape[key];
14+
rotate(point, angle);
15+
}
16+
return 'Shape rotated';
17+
};

JavaScript/1-HTTP/server.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
'use strict';
2+
3+
const http = require('http');
4+
const path = require('path');
5+
const fs = require('fs');
6+
7+
global.memory = new Map();
8+
const api = new Map();
9+
10+
const apiPath = './api/';
11+
12+
const cacheFile = name => {
13+
const filePath = apiPath + name;
14+
const key = path.basename(filePath, '.js');
15+
try {
16+
const libPath = require.resolve(filePath);
17+
delete require.cache[libPath];
18+
} catch (e) {
19+
return;
20+
}
21+
try {
22+
const method = require(filePath);
23+
api.set(key, method);
24+
} catch (e) {
25+
cache.delete(name);
26+
}
27+
};
28+
29+
const cacheFolder = path => {
30+
fs.readdir(path, (err, files) => {
31+
if (err) return;
32+
files.forEach(cacheFile);
33+
});
34+
};
35+
36+
const watch = path => {
37+
fs.watch(path, (event, file) => {
38+
cacheFile(file);
39+
});
40+
};
41+
42+
cacheFolder(apiPath);
43+
watch(apiPath);
44+
45+
setTimeout(() => {
46+
console.dir({ api });
47+
}, 1000);
48+
49+
http.createServer(async (req, res) => {
50+
const url = req.url === '/' ? '/index.html' : req.url;
51+
const [s, folder, file] = url.split('/');
52+
if (folder === 'api') {
53+
const method = api.get(file);
54+
const body = [];
55+
req.on('data', chunk => {
56+
body.push(chunk);
57+
}).on('end', async () => {
58+
const data = body.join('');
59+
const args = JSON.parse(data);
60+
try {
61+
const result = await method(...args);
62+
if (!result) {
63+
res.statusCode = 500;
64+
res.end('"Server error"');
65+
return;
66+
}
67+
res.end(JSON.stringify(result));
68+
} catch (err) {
69+
console.dir({ err });
70+
res.statusCode = 500;
71+
res.end('"Server error"');
72+
}
73+
});
74+
} else {
75+
const path = `./static/${folder}`;
76+
try {
77+
const data = await fs.promises.readFile(path);
78+
res.end(data);
79+
} catch (err) {
80+
res.statusCode = 404;
81+
res.end('"File is not found"');
82+
}
83+
}
84+
}).listen(8000);

JavaScript/1-HTTP/static/client.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
const buildAPI = methods => {
4+
const api = {};
5+
for (const method of methods) {
6+
api[method] = (...args) => new Promise((resolve, reject) => {
7+
const url = `/api/${method}`;
8+
console.log(url);
9+
fetch(url, {
10+
method: 'POST',
11+
headers: { 'Content-Type': 'application/json' },
12+
body: JSON.stringify(args),
13+
}).then(res => {
14+
const { status } = res;
15+
if (status !== 200) {
16+
reject(new Error(`Status Code: ${status}`));
17+
return;
18+
}
19+
resolve(res.json());
20+
});
21+
});
22+
}
23+
return api;
24+
};
25+
26+
const show = async () => {
27+
const svg = await api.render('Rect1');
28+
const output = document.getElementById('output');
29+
output.innerHTML = svg;
30+
};
31+
32+
const scenario = async () => {
33+
await api.rect('Rect1', -10, 10, 10, -10);
34+
await api.move('Rect1', 5, 5);
35+
await api.rotate('Rect1', 5);
36+
const data = await api.read('Rect1');
37+
await show();
38+
};
39+
40+
const api = buildAPI(['rect', 'move', 'rotate', 'read', 'render']);
41+
scenario();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="client.js"></script>
5+
</head>
6+
<body>
7+
<div id="output"></div>
8+
</body>
9+
</html>

0 commit comments

Comments
 (0)