@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make the Aphlict server more resilient.

Summary:
Currently, the Aphlict server will crash if invalid JSON data is `POST`ed to it. I have fixed this to, instead, return a 400. Also made some minor formatting changes.

Ref T4324. Ref T5284. Also, modify the data structure that is passed around (i.e. `POST`ed to the Aphlict server and broadcast to the Aphlict clients) to include the subscribers. Initially, I figured that we shouldn't expose this information to the clients... however, it is necessary for T4324 that the `AphlictMaster` is able to route a notification to the appropriate clients.

Test Plan:
Making the following `curl` request: `curl --data "{" http://localhost:22281/`.

**Before**
```
sudo ./bin/aphlict debug
Starting Aphlict server in foreground...
Launching server:

$ 'nodejs' '/usr/src/phabricator/src/applications/aphlict/management/../../../../support/aphlict/server/aphlict_server.js' --port='22280' --admin='22281' --host='localhost' --user='aphlict'

[Wed Jun 11 2014 17:07:51 GMT+0000 (UTC)] Started Server (PID 2033)
[Wed Jun 11 2014 17:07:55 GMT+0000 (UTC)]
<<< UNCAUGHT EXCEPTION! >>>

SyntaxError: Unexpected end of input
>>> Server exited!
```

**After**
(No output... the bad JSON is caught and a 400 is returned)

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T4324, T5284

Differential Revision: https://secure.phabricator.com/D9480

authored by

Joshua Spence and committed by
epriestley
ab432414 bb06e369

+65 -62
+1 -1
resources/celerity/map.php
··· 476 476 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 477 477 'rsrc/js/phuix/PHUIXActionView.js' => '6e8cefa4', 478 478 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 479 - 'rsrc/swf/aphlict.swf' => 'b7c2d7aa', 479 + 'rsrc/swf/aphlict.swf' => 'f45c3edc', 480 480 ), 481 481 'symbols' => 482 482 array(
+2 -4
src/applications/feed/PhabricatorFeedStoryPublisher.php
··· 176 176 177 177 private function sendNotification($chrono_key) { 178 178 $data = array( 179 - 'data' => array( 180 - 'key' => (string)$chrono_key, 181 - 'type' => 'notification', 182 - ), 179 + 'key' => (string)$chrono_key, 180 + 'type' => 'notification', 183 181 'subscribers' => $this->subscribedPHIDs, 184 182 ); 185 183
+1 -1
src/applications/notification/client/PhabricatorNotificationClient.php
··· 2 2 3 3 final class PhabricatorNotificationClient { 4 4 5 - const EXPECT_VERSION = 5; 5 + const EXPECT_VERSION = 6; 6 6 7 7 public static function getServerStatus() { 8 8 $uri = PhabricatorEnv::getEnvConfig('notification.server-uri');
+30 -23
support/aphlict/server/aphlict_server.js
··· 25 25 26 26 function parse_command_line_arguments(argv) { 27 27 var config = { 28 - port : 22280, 29 - admin : 22281, 30 - host : '127.0.0.1', 31 - user : null, 28 + port: 22280, 29 + admin: 22281, 30 + host: '127.0.0.1', 31 + user: null, 32 32 log: '/var/log/aphlict.log' 33 33 }; 34 34 ··· 36 36 var arg = argv[ii]; 37 37 var matches = arg.match(/^--([^=]+)=(.*)$/); 38 38 if (!matches) { 39 - throw new Error("Unknown argument '"+arg+"'!"); 39 + throw new Error("Unknown argument '" + arg + "'!"); 40 40 } 41 41 if (!(matches[1] in config)) { 42 - throw new Error("Unknown argument '"+matches[1]+"'!"); 42 + throw new Error("Unknown argument '" + matches[1] + "'!"); 43 43 } 44 44 config[matches[1]] = matches[2]; 45 45 } ··· 52 52 53 53 if (process.getuid() !== 0) { 54 54 console.log( 55 - "ERROR: "+ 56 - "This server must be run as root because it needs to bind to privileged "+ 57 - "port 843 to start a Flash policy server. It will downgrade to run as a "+ 58 - "less-privileged user after binding if you pass a user in the command "+ 55 + "ERROR: " + 56 + "This server must be run as root because it needs to bind to privileged " + 57 + "port 843 to start a Flash policy server. It will downgrade to run as a " + 58 + "less-privileged user after binding if you pass a user in the command " + 59 59 "line arguments with '--user=alincoln'."); 60 60 process.exit(1); 61 61 } 62 62 63 63 var net = require('net'); 64 - var http = require('http'); 64 + var http = require('http'); 65 65 var url = require('url'); 66 66 67 - process.on('uncaughtException', function (err) { 67 + process.on('uncaughtException', function(err) { 68 68 debug.log("\n<<< UNCAUGHT EXCEPTION! >>>\n\n" + err); 69 69 process.exit(1); 70 70 }); ··· 95 95 debug.log('<%s> Ended Connection', listener.getDescription()); 96 96 }); 97 97 98 - socket.on('error', function (e) { 98 + socket.on('error', function(e) { 99 99 debug.log('<%s> Error: %s', listener.getDescription(), e); 100 100 }); 101 101 ··· 107 107 var start_time = new Date().getTime(); 108 108 109 109 var receive_server = http.createServer(function(request, response) { 110 - response.writeHead(200, {'Content-Type' : 'text/plain'}); 111 - 112 110 // Publishing a notification. 113 111 if (request.method == 'POST') { 114 112 var body = ''; 115 113 116 - request.on('data', function (data) { 114 + request.on('data', function(data) { 117 115 body += data; 118 116 }); 119 117 120 - request.on('end', function () { 121 - ++messages_in; 118 + request.on('end', function() { 119 + try { 120 + var msg = JSON.parse(body); 122 121 123 - var msg = JSON.parse(body); 124 - debug.log('notification: ' + JSON.stringify(msg)); 125 - broadcast(msg.data); 126 - response.end(); 122 + debug.log('notification: ' + JSON.stringify(msg)); 123 + ++messages_in; 124 + broadcast(msg); 125 + 126 + response.writeHead(200, {'Content-Type': 'text/plain'}); 127 + } catch (err) { 128 + response.statusCode = 400; 129 + response.write('400 Bad Request'); 130 + } finally { 131 + response.end(); 132 + } 127 133 }); 128 134 } else if (request.url == '/status/') { 129 135 request.on('data', function(data) { ··· 139 145 'messages.in': messages_in, 140 146 'messages.out': messages_out, 141 147 'log': config.log, 142 - 'version': 5 148 + 'version': 6 143 149 }; 144 150 151 + response.writeHead(200, {'Content-Type': 'text/plain'}); 145 152 response.write(JSON.stringify(status)); 146 153 response.end(); 147 154 });
+2 -2
support/aphlict/server/lib/AphlictFlashPolicyServer.js
··· 17 17 _accessPort: null, 18 18 _debug: null, 19 19 20 - setDebugLog : function(log) { 20 + setDebugLog: function(log) { 21 21 this._debug = log; 22 22 return this; 23 23 }, 24 24 25 - setAccessPort : function(port) { 25 + setAccessPort: function(port) { 26 26 this._accessPort = port; 27 27 return this; 28 28 },
+8 -8
support/aphlict/server/lib/AphlictListener.js
··· 1 1 var JX = require('javelin').JX; 2 2 3 3 JX.install('AphlictListener', { 4 - construct : function(id, socket) { 4 + construct: function(id, socket) { 5 5 this._id = id; 6 6 this._socket = socket; 7 7 }, 8 8 9 - members : { 10 - _id : null, 11 - _socket : null, 9 + members: { 10 + _id: null, 11 + _socket: null, 12 12 13 - getID : function() { 13 + getID: function() { 14 14 return this._id; 15 15 }, 16 16 17 - getSocket : function() { 17 + getSocket: function() { 18 18 return this._socket; 19 19 }, 20 20 21 - getDescription : function() { 21 + getDescription: function() { 22 22 return 'Listener/' + this.getID(); 23 23 }, 24 24 25 - writeMessage : function(message) { 25 + writeMessage: function(message) { 26 26 var serial = JSON.stringify(message); 27 27 28 28 var length = Buffer.byteLength(serial, 'utf8');
+13 -15
support/aphlict/server/lib/AphlictListenerList.js
··· 2 2 JX.require('AphlictListener', __dirname); 3 3 4 4 JX.install('AphlictListenerList', { 5 - construct : function() { 5 + construct: function() { 6 6 this._listeners = {}; 7 7 }, 8 8 9 - members : { 10 - _listeners : null, 11 - _nextID : 0, 12 - _activeListenerCount : 0, 13 - _totalListenerCount : 0, 9 + members: { 10 + _listeners: null, 11 + _nextID: 0, 12 + _activeListenerCount: 0, 13 + _totalListenerCount: 0, 14 14 15 - addListener : function(socket) { 16 - var listener = new JX.AphlictListener( 17 - this._generateNextID(), 18 - socket); 15 + addListener: function(socket) { 16 + var listener = new JX.AphlictListener(this._generateNextID(), socket); 19 17 20 18 this._listeners[listener.getID()] = listener; 21 19 this._activeListenerCount++; ··· 24 22 return listener; 25 23 }, 26 24 27 - removeListener : function(listener) { 25 + removeListener: function(listener) { 28 26 var id = listener.getID(); 29 27 if (id in this._listeners) { 30 28 delete this._listeners[id]; ··· 32 30 } 33 31 }, 34 32 35 - getListeners : function() { 33 + getListeners: function() { 36 34 return this._listeners; 37 35 }, 38 36 39 - getActiveListenerCount : function() { 37 + getActiveListenerCount: function() { 40 38 return this._activeListenerCount; 41 39 }, 42 40 43 - getTotalListenerCount : function() { 41 + getTotalListenerCount: function() { 44 42 return this._totalListenerCount; 45 43 }, 46 44 47 - _generateNextID : function() { 45 + _generateNextID: function() { 48 46 do { 49 47 this._nextID = ((this._nextID + 1) % 1000000000000); 50 48 } while (this._nextID in this._listeners);
+7 -7
support/aphlict/server/lib/AphlictLog.js
··· 4 4 var util = require('util'); 5 5 6 6 JX.install('AphlictLog', { 7 - construct : function() { 7 + construct: function() { 8 8 this._writeToLogs = []; 9 9 this._writeToConsoles = []; 10 10 }, 11 11 12 - members : { 13 - _writeToConsoles : null, 14 - _writeToLogs : null, 12 + members: { 13 + _writeToConsoles: null, 14 + _writeToLogs: null, 15 15 16 - addLogfile : function(path) { 16 + addLogfile: function(path) { 17 17 var options = { 18 18 flags: 'a', 19 19 encoding: 'utf8', ··· 27 27 return this; 28 28 }, 29 29 30 - addConsole : function(console) { 30 + addConsole: function(console) { 31 31 this._writeToConsoles.push(console); 32 32 return this; 33 33 }, 34 34 35 - log : function(pattern) { 35 + log: function(pattern) { 36 36 var str = util.format.apply(null, arguments); 37 37 var date = new Date().toLocaleString(); 38 38 str = '[' + date + '] ' + str;
+1 -1
support/aphlict/server/lib/javelin.js
··· 6 6 7 7 // NOTE: This is faking out a piece of code in JX.install which waits for 8 8 // Stratcom before running static initializers. 9 - JX.Stratcom = {ready : true}; 9 + JX.Stratcom = {ready: true}; 10 10 JX.require('core/Event'); 11 11 JX.require('core/Stratcom'); 12 12
webroot/rsrc/swf/aphlict.swf

This is a binary file and will not be displayed.