Aidd a maximum speed size

This commit is contained in:
Will Hunt 2024-02-29 18:33:46 +00:00
parent 6c6cd6ee92
commit 1ef0026509
6 changed files with 24 additions and 3 deletions

View File

@ -10,6 +10,7 @@ import { GetConnectionsResponseItem } from "../provisioning/api";
import { readFeed, sanitizeHtml } from "../libRs";
import UserAgent from "../UserAgent";
import { retry, retryMatrixErrorFilter } from "../PromiseUtil";
import { BridgeConfigFeeds } from "../config/Config";
const log = new Logger("FeedConnection");
const md = new markdown({
html: true,
@ -64,7 +65,7 @@ export class FeedConnection extends BaseConnection implements IConnection {
return new FeedConnection(roomId, event.stateKey, event.content, intent);
}
static async validateUrl(url: string): Promise<void> {
static async validateUrl(url: string, config: BridgeConfigFeeds): Promise<void> {
try {
new URL(url);
} catch (ex) {
@ -75,6 +76,7 @@ export class FeedConnection extends BaseConnection implements IConnection {
await readFeed(url, {
userAgent: UserAgent,
pollTimeoutSeconds: VALIDATION_FETCH_TIMEOUT_S,
maximumFeedSizeMb: config.maximumFeedSizeMB,
});
} catch (ex) {
throw new ApiError(`Could not read feed from URL: ${ex.message}`, ErrCode.BadValue);
@ -113,7 +115,7 @@ export class FeedConnection extends BaseConnection implements IConnection {
}
const state = this.validateState(data);
await FeedConnection.validateUrl(state.url);
await FeedConnection.validateUrl(state.url, config.feeds);
const connection = new FeedConnection(roomId, state.url, state, intent);
await intent.underlyingClient.sendStateEvent(roomId, FeedConnection.CanonicalEventType, state.url, state);

View File

@ -312,7 +312,7 @@ export class SetupConnection extends CommandConnection {
// provisionConnection will check it again, but won't give us a nice CommandError on failure
try {
await FeedConnection.validateUrl(url);
await FeedConnection.validateUrl(url, this.config.feeds);
} catch (err: unknown) {
log.debug(`Feed URL '${url}' failed validation: ${err}`);
if (err instanceof ApiError) {

View File

@ -251,6 +251,7 @@ export interface BridgeConfigFeedsYAML {
pollIntervalSeconds?: number;
pollConcurrency?: number;
pollTimeoutSeconds?: number;
maximumFeedSizeMB?: number;
}
export class BridgeConfigFeeds {
@ -259,6 +260,9 @@ export class BridgeConfigFeeds {
public pollTimeoutSeconds: number;
public pollConcurrency: number;
@configKey("The maximum response size of a feed on first load. Oversized responses will prevent a connection from being created.", true)
public maximumFeedSizeMB: number;
constructor(yaml: BridgeConfigFeedsYAML) {
this.enabled = yaml.enabled;
this.pollConcurrency = yaml.pollConcurrency ?? 4;
@ -266,6 +270,11 @@ export class BridgeConfigFeeds {
assert.strictEqual(typeof this.pollIntervalSeconds, "number");
this.pollTimeoutSeconds = yaml.pollTimeoutSeconds ?? 30;
assert.strictEqual(typeof this.pollTimeoutSeconds, "number");
this.maximumFeedSizeMB = yaml.maximumFeedSizeMB ?? 25;
assert.strictEqual(typeof this.maximumFeedSizeMB, "number");
if (this.maximumFeedSizeMB < 1) {
throw new ConfigError('feeds.maximumFeedSizeMB', 'Must be at least 1MB or greater');
}
}
@hideKey()

View File

@ -124,6 +124,7 @@ export const DefaultConfigRoot: BridgeConfigRoot = {
pollIntervalSeconds: 600,
pollTimeoutSeconds: 30,
pollConcurrency: 4,
maximumFeedSizeMB: 25,
},
provisioning: {
secret: "!secretToken"

View File

@ -215,6 +215,7 @@ export class FeedReader {
etag,
lastModified,
userAgent: UserAgent,
maximumFeedSizeMb: this.config.maximumFeedSizeMB,
});
// Store any entity tags/cache times.

View File

@ -37,6 +37,7 @@ pub struct ReadFeedOptions {
pub etag: Option<String>,
pub poll_timeout_seconds: i64,
pub user_agent: String,
pub maximum_feed_size_mb: i64,
}
#[derive(Serialize, Debug, Deserialize)]
@ -202,6 +203,13 @@ pub async fn js_read_feed(url: String, options: ReadFeedOptions) -> Result<FeedR
match req.headers(headers).send().await {
Ok(res) => {
let res_headers = res.headers().clone();
if res.content_length().unwrap_or(0) > options.maximum_feed_size_mb as u64 {
return Err(JsError::new(
Status::Unknown,
"Feed exceeded maximum size",
));
}
match res.status() {
StatusCode::OK => match res.text().await {
Ok(body) => match js_parse_feed(body) {