-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathapp.js
122 lines (103 loc) · 4.25 KB
/
app.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
var Redis = require('redis');
var Safebrowsing = require('../lib/index.js');
var express = require('express');
var bodyParser = require('body-parser');
// There's two core pieces of configuration information:
//
// - The API key for accessing the Google Safebrowsing API.
// - The cache wrapper and connection to appropriate back-end data store.
// The cache object is intended to be stateless (in that it acts as a
// transparent relay to the backend store), so we can re-use it across
// multiple Fetchers and Matchers.
var API_KEY = '<safebrowsing api key>';
var cache = new Safebrowsing.RedisCache(new Redis.createClient());
// # Class: Fetcher
//
// A Fetcher is an object that manages updating our copy of the cache.
// Only create **one instance** of this in your entire application.
// It automatically fetches new prefix data from the API at regular intervals
// from [GoogleMalwareList, GooglePhishingList].
//
// ## Wait, why no parallelism?
//
// Since the Safebrowsing API doesn't allow parallel downloads, there's no
// advantage to trying to make this parallel. It also simplfies the cache
// design if this is the only system that can fetch and mutate the cache.
//
// If you're building a real-world application you're going to want to probably
// slap this behind a thrift service or some other system that lets you access
// it from multiple separate boxes.
var fetcher = new Safebrowsing.Fetcher(cache, API_KEY);
// # Class: Matcher
//
// A Matcher is an object that manages checking if URLs are blacklisted.
// It does not mutate the cache, so you can create as many Matchers as you want.
var matcher = new Safebrowsing.Matcher(cache);
// # Checking URLs
//
// Suppose we want to create a web service endpoint that checks URLs.
// We're going to create a POST endpoint that you can call and then it'll
// give you back information on whether the list was found in any blacklists.
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.set('views', './views');
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.render('index');
});
app.post('/', function(req, res) {
var url = req.body.url;
// We can check whether something is in our cached set of list data with
// Matcher.match. It checks the lists [GoogleMalwareList, GooglePhishingList].
//
// There's three states a list match could be in:
//
// - No match: Not found on the prefix list. **It's clean.**
// - Inconclusive: Found on the prefix list, but don't have prefix details
// to match against, and thus can't show a warning yet.
// We'll need to do a detail fetch first.
// - Match: Found on the prefix list and the prefix detail list.
// **We should show a warning.**
var matches = matcher.match(url);
// ## Class: MatchResults
//
// It returns a MatchResults object, that lets you easily filter the matching
// results futher for use in a UI or to do detail fetches.
//
// ### No Match Filtering
//
// - `results.getNoMatch()` Returns a list of the list non-matches.
//
// ### Match Filtering
//
// - `results.getMatch()` Returns a list of the list matches and metadata.
//
// ### Inconclusive Filtering
//
// - `results.getInconclusive()` Returns a list of the inconclusive results.
// - `results.getInconclusiveRequest()` Returns an object you can pass to
// Fetcher.fetchInconclusive to get details.
// - `results.resolveInconclusive()` Provided that fetchInconclusive has
// completed, you can call this to rematch the inconclusive lists with a
// promise for new, updated (not mutated) MatchResults.
matches
.then(function(results) {
if (results.getInconclusive().length > 0) {
return fetcher.fetchInconclusive(results.getInconclusiveRequest())
.then(function() { return results.resolveInconclusive(); });
}
return results;
})
.then(function(results) {
res.json({
url: url,
results: results.getMatch()
});
});
});
var server = app.listen(3001, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
module.exports = app;