forked from pulumi/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
134 lines (115 loc) · 4.66 KB
/
index.ts
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
125
126
127
128
129
130
131
132
133
134
// Copyright 2016-2018, Pulumi Corporation. All rights reserved.
import * as cloud from "@pulumi/cloud";
import * as cache from "./cache";
import * as express from "express";
import * as fs from "fs";
import * as mime from "mime-types";
type AsyncRequestHandler = (req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>;
const asyncMiddleware = (fn: AsyncRequestHandler) => {
return (req: express.Request, res: express.Response, next: express.NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
// Create a table `urls`, with `name` as primary key.
let urlTable = new cloud.Table("urls", "name");
// Create a cache of frequently accessed urls.
let urlCache = new cache.Cache("urlcache");
// Create a web server.
let endpoint = new cloud.HttpServer("urlshortener", () => {
let app = express();
// GET /url lists all URLs currently registered.
app.get("/url", asyncMiddleware(async (req, res) => {
try {
let items = await urlTable.scan();
res.status(200).json(items);
console.log(`GET /url retrieved ${items.length} items`);
} catch (err) {
res.status(500).json(err.stack);
console.log(`GET /url error: ${err.stack}`);
}
}));
// GET /url/{name} redirects to the target URL based on a short-name.
app.get("/url/:name", asyncMiddleware(async (req, res) => {
let name = req.params.name
try {
// First try the Redis cache.
let url = await urlCache.get(name);
if (url) {
console.log(`Retrieved value from Redis: ${url}`);
res.setHeader("X-Powered-By", "redis");
}
else {
// If we didn't find it in the cache, consult the table.
let value = await urlTable.get({name});
url = value && value.url;
if (url) {
urlCache.set(name, url); // cache it for next time.
}
}
// If we found an entry, 301 redirect to it; else, 404.
if (url) {
res.setHeader("Location", url);
res.status(302);
res.end("");
console.log(`GET /url/${name} => ${url}`)
}
else {
res.status(404);
res.end("");
console.log(`GET /url/${name} is missing (404)`)
}
} catch (err) {
res.status(500).json(err.stack);
console.log(`GET /url/${name} error: ${err.stack}`);
}
}));
// POST /url registers a new URL with a given short-name.
app.post("/url", asyncMiddleware(async (req, res) => {
const url = <string>req.query["url"];
const name = <string>req.query["name"];
try {
await urlTable.insert({ name, url });
await urlCache.set(name, url);
res.json({ shortenedURLName: name });
console.log(`POST /url/${name} => ${url}`);
} catch (err) {
res.status(500).json(err.stack);
console.log(`POST /url/${name} => ${url} error: ${err.stack}`);
}
}));
// Serve all files in the www directory to the root.
// Note: www will be auto-included using config. either
// cloud-aws:functionIncludePaths or
// cloud-azure:functionIncludePaths
// staticRoutes(app, "/", "www");
app.use("/", express.static("www"));
app.get("*", (req, res) => {
res.json({ uncaught: { url: req.url, baseUrl: req.baseUrl, originalUrl: req.originalUrl, version: process.version } });
});
return app;
});
function staticRoutes(app: express.Express, path: string, root: string) {
for (const child of fs.readdirSync("./" + root)) {
app.get(path + child, (req, res) => {
try
{
// console.log("Trying to serve: " + path + child)
// res.json({ serving: child });
const localPath = "./" + root + "/" + child;
const contents = fs.readFileSync(localPath);
var type = mime.contentType(child)
if (type) {
res.setHeader('Content-Type', type);
}
const stat = fs.statSync(path);
res.setHeader("Content-Length", stat.size);
res.end(contents);
}
catch (err) {
console.log(JSON.stringify({ message: err.message, stack: err.stack }));
res.json({ message: err.message, stack: err.stack });
}
});
}
}
export let endpointUrl = endpoint.url.apply(u => u + "index.html");