Perf dashboard always re-generate measurement set JSON
[WebKit.git] / Websites / perf.webkit.org / tools / js / remote.js
1 'use strict';
2
3 let assert = require('assert');
4 let http = require('http');
5 let https = require('https');
6 let querystring = require('querystring');
7
8 class RemoteAPI {
9     constructor(server)
10     {
11         this._server = null;
12         this._cookies = new Map;
13         if (server)
14             this.configure(server);
15     }
16
17     url(path)
18     {
19         let scheme = this._server.scheme;
20         let port = this._server.port;
21         let portSuffix = this._server.port == this._server.defaultPort ? '' : `:${port}`;
22         if (path.charAt(0) != '/')
23             path = '/' + path;
24         return `${scheme}://${this._server.host}${portSuffix}${path}`;
25     }
26
27     configure(server)
28     {
29         assert(server.scheme === 'http' || server.scheme === 'https');
30         assert.equal(typeof(server.host), 'string', 'host should be a string');
31         assert(!server.port || typeof(server.port) == 'number', 'port should be a number');
32
33         let auth = null;
34         if (server.auth) {
35             assert.equal(typeof(server.auth), 'object', 'auth should be a dictionary with username and password as keys');
36             assert.equal(typeof(server.auth.username), 'string', 'auth should contain a string username');
37             assert.equal(typeof(server.auth.password), 'string', 'auth should contain a string password');
38             auth = {
39                 username: server.auth.username,
40                 password: server.auth.password,
41             };
42         }
43
44         const defaultPort = server.scheme == 'http' ? 80 : 443;
45         this._server = {
46             scheme: server.scheme,
47             host: server.host,
48             port: server.port || defaultPort,
49             defaultPort: defaultPort,
50             auth: auth,
51         };
52     }
53
54     clearCookies() { this._cookies = new Map; }
55
56     getJSON(path)
57     {
58         return this.sendHttpRequest(path, 'GET', null, null).then(function (result) {
59             return JSON.parse(result.responseText);
60         });
61     }
62
63     getJSONWithStatus(path)
64     {
65         return this.getJSON(path).then(function (result) {
66             if (result['status'] != 'OK')
67                 return Promise.reject(result);
68             return result;
69         });
70     }
71
72     postJSON(path, data)
73     {
74         const contentType = 'application/json';
75         const payload = JSON.stringify(data || {});
76         return this.sendHttpRequest(path, 'POST', 'application/json', payload).then(function (result) {
77             try {
78                 return JSON.parse(result.responseText);
79             } catch (error) {
80                 console.error(result.responseText);
81                 throw error;
82             }
83         });
84     }
85
86     postJSONWithStatus(path, data)
87     {
88         return this.postJSON(path, data).then(function (result) {
89             if (result['status'] != 'OK')
90                 return Promise.reject(result);
91             return result;
92         });
93     }
94
95     postFormUrlencodedData(path, data)
96     {
97         const contentType = 'application/x-www-form-urlencoded';
98         const payload = querystring.stringify(data);
99         return this.sendHttpRequest(path, 'POST', contentType, payload).then(function (result) {
100             return result.responseText;
101         });
102     }
103
104     sendHttpRequest(path, method, contentType, content)
105     {
106         let server = this._server;
107         const self = this;
108         return new Promise(function (resolve, reject) {
109             let options = {
110                 hostname: server.host,
111                 port: server.port,
112                 auth: server.auth ? server.auth.username + ':' + server.auth.password : null,
113                 method: method,
114                 path: path,
115             };
116
117             let request = (server.scheme == 'http' ? http : https).request(options, function (response) {
118                 let responseText = '';
119                 response.setEncoding('utf8');
120                 response.on('data', function (chunk) { responseText += chunk; });
121                 response.on('end', function () {
122                     if (response.statusCode != 200) {
123                         reject(response.statusCode);
124                         return;
125                     }
126
127                     if ('set-cookie' in response.headers) {
128                         for (const cookie of response.headers['set-cookie']) {
129                             var nameValue = cookie.split('=')
130                             self._cookies.set(nameValue[0], nameValue[1]);
131                         }
132                     }
133                     resolve({statusCode: response.statusCode, responseText: responseText});
134                 });
135             });
136
137             request.on('error', reject);
138
139             if (contentType)
140                 request.setHeader('Content-Type', contentType);
141
142             if (self._cookies.size) {
143                 request.setHeader('Cookie', Array.from(self._cookies.keys()).map(function (key) {
144                     return `${key}=${self._cookies.get(key)}`;
145                 }).join('; '));
146             }
147
148             if (content)
149                 request.write(content);
150
151             request.end();
152         });
153     }
154 };
155
156 if (typeof module != 'undefined')
157     module.exports.RemoteAPI = RemoteAPI;