-
Notifications
You must be signed in to change notification settings - Fork 1
/
runkit.js
124 lines (109 loc) · 2.91 KB
/
runkit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const tt = require("tar-transform");
const fetch = require("node-fetch");
const routes = {
/** no-op */
"original-file": () =>
tt.transform({
onEntry(entry) {
this.push(entry);
},
}),
/** Transform path for each entry: prefix with my-root/ */
"transform-entry-path": () =>
tt.transform({
onEntry(entry) {
const headers = this.util.headersWithNewName(
entry.headers,
"my-root/" + entry.headers.name,
);
this.push({ ...entry, headers });
},
}),
/** edit file content: prefix *.txt files */
"edit-file-content": () =>
tt.transform({
async onEntry(entry) {
if (entry.headers.name.endsWith(".txt")) {
const oldContent = await this.util.stringContentOfTarEntry(entry);
const newContent = "HACKED BY tar-transform\n" + oldContent;
this.push({
headers: entry.headers,
content: newContent,
});
} else {
this.push(entry);
}
},
}),
/** remove files from tarball: remove *.png files */
"remove-file": () =>
tt.transform({
onEntry(entry) {
if (entry.headers.name.endsWith(".png")) {
this.pass(entry);
} else {
this.push(entry);
}
},
}),
/**
* add files to tarball:
* add a file including the directory structure using context
*/
"add-file": () =>
tt.transform({
initCtx: [],
onEntry(entry) {
this.ctx.push([entry.headers.name, entry.headers.type]);
this.push(entry);
},
onEnd() {
this.push({
headers: { name: "file-structure.txt" },
content: this.ctx
.map(([name, type]) => `[${type}]\t${name}`)
.join("\n"),
});
},
}),
};
exports.endpoint = async (req, resp) => {
const { pathname } = require("url").parse(req.url);
const getTransformStream = routes[pathname.slice(1)];
if (!getTransformStream) {
resp.end("invalid request url: " + resp.url);
return;
}
const tgzStream = (
await fetch(
"https://runkit.io/equalma/tar-transform-pack/branches/master/tgz",
)
).body;
const extractStream = tt.extract();
const transformStream = getTransformStream();
const packStream = tt.pack({ gzip: true });
resp.setHeader("Content-Type", "application/octet-stream");
resp.setHeader(
"Content-Disposition",
`attachment; filename="tar-transform-demo-${pathname.slice(1)}.tgz"`,
);
tgzStream
.pipe(extractStream)
.pipe(transformStream)
.pipe(packStream)
.pipe(resp)
.on("error", console.error);
};
const urlRoot = process.env.RUNKIT_ENDPOINT_URL;
const html = Object.keys(routes)
.map(route => {
const url = urlRoot + "/" + route;
return `
<form method="get" action="${url}">
<button type="submit">${route}</button>
<input readonly value="${url}">
</form>
`;
})
.join("\n");
html;