mirror of
https://github.com/mastodon/mastodon.git
synced 2024-08-20 21:08:15 -07:00
Compare commits
2 commits
0b56471f6b
...
89bdffc616
Author | SHA1 | Date | |
---|---|---|---|
|
89bdffc616 | ||
|
c8bc986323 |
6 changed files with 684 additions and 465 deletions
|
@ -83,3 +83,4 @@ AUTHORS.md
|
||||||
|
|
||||||
# Process a few selected JS files
|
# Process a few selected JS files
|
||||||
!lint-staged.config.js
|
!lint-staged.config.js
|
||||||
|
!/streaming/*.js
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class RequestError extends Error {
|
||||||
*/
|
*/
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = "RequestError";
|
this.name = 'RequestError';
|
||||||
this.status = 400;
|
this.status = 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export class AuthenticationError extends Error {
|
||||||
*/
|
*/
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = "AuthenticationError";
|
this.name = 'AuthenticationError';
|
||||||
this.status = 401;
|
this.status = 401;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1081
streaming/index.js
1081
streaming/index.js
File diff suppressed because it is too large
Load diff
|
@ -31,18 +31,21 @@ function sanitizeRequestLog(req) {
|
||||||
const log = pinoHttpSerializers.req(req);
|
const log = pinoHttpSerializers.req(req);
|
||||||
if (typeof log.url === 'string' && log.url.includes('access_token')) {
|
if (typeof log.url === 'string' && log.url.includes('access_token')) {
|
||||||
// Doorkeeper uses SecureRandom.urlsafe_base64 per RFC 6749 / RFC 6750
|
// Doorkeeper uses SecureRandom.urlsafe_base64 per RFC 6749 / RFC 6750
|
||||||
log.url = log.url.replace(/(access_token)=([a-zA-Z0-9\-_]+)/gi, '$1=[Redacted]');
|
log.url = log.url.replace(
|
||||||
|
/(access_token)=([a-zA-Z0-9\-_]+)/gi,
|
||||||
|
'$1=[Redacted]',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const logger = pino({
|
export const logger = pino({
|
||||||
name: "streaming",
|
name: 'streaming',
|
||||||
// Reformat the log level to a string:
|
// Reformat the log level to a string:
|
||||||
formatters: {
|
formatters: {
|
||||||
level: (label) => {
|
level: (label) => {
|
||||||
return {
|
return {
|
||||||
level: label
|
level: label,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -54,17 +57,17 @@ export const logger = pino({
|
||||||
'req.headers["sec-websocket-protocol"]',
|
'req.headers["sec-websocket-protocol"]',
|
||||||
'req.headers.authorization',
|
'req.headers.authorization',
|
||||||
'req.headers.cookie',
|
'req.headers.cookie',
|
||||||
'req.query.access_token'
|
'req.query.access_token',
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const httpLogger = pinoHttp({
|
export const httpLogger = pinoHttp({
|
||||||
logger,
|
logger,
|
||||||
genReqId: generateRequestId,
|
genReqId: generateRequestId,
|
||||||
serializers: {
|
serializers: {
|
||||||
req: sanitizeRequestLog
|
req: sanitizeRequestLog,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,11 +93,11 @@ export function createWebsocketLogger(request, resolvedAccount) {
|
||||||
|
|
||||||
return logger.child({
|
return logger.child({
|
||||||
req: {
|
req: {
|
||||||
id: request.id
|
id: request.id,
|
||||||
},
|
},
|
||||||
account: {
|
account: {
|
||||||
id: resolvedAccount.accountId ?? null
|
id: resolvedAccount.accountId ?? null,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +107,10 @@ export function createWebsocketLogger(request, resolvedAccount) {
|
||||||
* @param {string} environment
|
* @param {string} environment
|
||||||
*/
|
*/
|
||||||
export function initializeLogLevel(env, environment) {
|
export function initializeLogLevel(env, environment) {
|
||||||
if (env.LOG_LEVEL && Object.keys(logger.levels.values).includes(env.LOG_LEVEL)) {
|
if (
|
||||||
|
env.LOG_LEVEL &&
|
||||||
|
Object.keys(logger.levels.values).includes(env.LOG_LEVEL)
|
||||||
|
) {
|
||||||
logger.level = env.LOG_LEVEL;
|
logger.level = env.LOG_LEVEL;
|
||||||
} else if (environment === 'development') {
|
} else if (environment === 'development') {
|
||||||
logger.level = 'debug';
|
logger.level = 'debug';
|
||||||
|
|
|
@ -55,7 +55,7 @@ export function setupMetrics(channels, pgPool) {
|
||||||
const connectedChannels = new metrics.Gauge({
|
const connectedChannels = new metrics.Gauge({
|
||||||
name: 'connected_channels',
|
name: 'connected_channels',
|
||||||
help: 'The number of channels the streaming server is streaming to',
|
help: 'The number of channels the streaming server is streaming to',
|
||||||
labelNames: [ 'type', 'channel' ]
|
labelNames: ['type', 'channel'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const redisSubscriptions = new metrics.Gauge({
|
const redisSubscriptions = new metrics.Gauge({
|
||||||
|
@ -65,13 +65,13 @@ export function setupMetrics(channels, pgPool) {
|
||||||
|
|
||||||
const redisMessagesReceived = new metrics.Counter({
|
const redisMessagesReceived = new metrics.Counter({
|
||||||
name: 'redis_messages_received_total',
|
name: 'redis_messages_received_total',
|
||||||
help: 'The total number of messages the streaming server has received from redis subscriptions'
|
help: 'The total number of messages the streaming server has received from redis subscriptions',
|
||||||
});
|
});
|
||||||
|
|
||||||
const messagesSent = new metrics.Counter({
|
const messagesSent = new metrics.Counter({
|
||||||
name: 'messages_sent_total',
|
name: 'messages_sent_total',
|
||||||
help: 'The total number of messages the streaming server sent to clients per connection type',
|
help: 'The total number of messages the streaming server sent to clients per connection type',
|
||||||
labelNames: [ 'type' ]
|
labelNames: ['type'],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prime the gauges so we don't loose metrics between restarts:
|
// Prime the gauges so we don't loose metrics between restarts:
|
||||||
|
@ -80,7 +80,7 @@ export function setupMetrics(channels, pgPool) {
|
||||||
connectedClients.set({ type: 'eventsource' }, 0);
|
connectedClients.set({ type: 'eventsource' }, 0);
|
||||||
|
|
||||||
// For each channel, initialize the gauges at zero; There's only a finite set of channels available
|
// For each channel, initialize the gauges at zero; There's only a finite set of channels available
|
||||||
channels.forEach(( channel ) => {
|
channels.forEach((channel) => {
|
||||||
connectedChannels.set({ type: 'websocket', channel }, 0);
|
connectedChannels.set({ type: 'websocket', channel }, 0);
|
||||||
connectedChannels.set({ type: 'eventsource', channel }, 0);
|
connectedChannels.set({ type: 'eventsource', channel }, 0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const FALSE_VALUES = [
|
const FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'];
|
||||||
false,
|
|
||||||
0,
|
|
||||||
'0',
|
|
||||||
'f',
|
|
||||||
'F',
|
|
||||||
'false',
|
|
||||||
'FALSE',
|
|
||||||
'off',
|
|
||||||
'OFF',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} value
|
* @param {any} value
|
||||||
|
@ -24,8 +14,10 @@ export function isTruthy(value) {
|
||||||
* See app/lib/ascii_folder.rb for the canon definitions
|
* See app/lib/ascii_folder.rb for the canon definitions
|
||||||
* of these constants
|
* of these constants
|
||||||
*/
|
*/
|
||||||
const NON_ASCII_CHARS = 'ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž';
|
const NON_ASCII_CHARS =
|
||||||
const EQUIVALENT_ASCII_CHARS = 'AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz';
|
'ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž';
|
||||||
|
const EQUIVALENT_ASCII_CHARS =
|
||||||
|
'AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} str
|
* @param {string} str
|
||||||
|
@ -34,7 +26,7 @@ const EQUIVALENT_ASCII_CHARS = 'AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEe
|
||||||
export function foldToASCII(str) {
|
export function foldToASCII(str) {
|
||||||
const regex = new RegExp(NON_ASCII_CHARS.split('').join('|'), 'g');
|
const regex = new RegExp(NON_ASCII_CHARS.split('').join('|'), 'g');
|
||||||
|
|
||||||
return str.replace(regex, function(match) {
|
return str.replace(regex, function (match) {
|
||||||
const index = NON_ASCII_CHARS.indexOf(match);
|
const index = NON_ASCII_CHARS.indexOf(match);
|
||||||
return EQUIVALENT_ASCII_CHARS[index];
|
return EQUIVALENT_ASCII_CHARS[index];
|
||||||
});
|
});
|
||||||
|
@ -45,7 +37,10 @@ export function foldToASCII(str) {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function normalizeHashtag(str) {
|
export function normalizeHashtag(str) {
|
||||||
return foldToASCII(str.normalize('NFKC').toLowerCase()).replace(/[^\p{L}\p{N}_\u00b7\u200c]/gu, '');
|
return foldToASCII(str.normalize('NFKC').toLowerCase()).replace(
|
||||||
|
/[^\p{L}\p{N}_\u00b7\u200c]/gu,
|
||||||
|
'',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue