@evanp/activitypub-bot 0.39.0 → 0.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/activitypubclient.js +32 -7
- package/lib/app.js +39 -24
- package/lib/httpmessagesignature.js +1 -1
- package/lib/ratelimiter.js +1 -1
- package/lib/remoteobjectcache.js +1 -1
- package/lib/signaturepolicystorage.js +1 -1
- package/package.json +1 -1
package/lib/activitypubclient.js
CHANGED
|
@@ -4,7 +4,6 @@ import path from 'node:path'
|
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
|
|
6
6
|
import fetch from 'node-fetch'
|
|
7
|
-
import { ProblemDetailsError } from './errors.js'
|
|
8
7
|
|
|
9
8
|
import as2 from './activitystreams.js'
|
|
10
9
|
import { SignaturePolicyStorage } from './signaturepolicystorage.js'
|
|
@@ -23,6 +22,32 @@ const COLLECTION_TYPES = [
|
|
|
23
22
|
`${NS}OrderedCollection`
|
|
24
23
|
]
|
|
25
24
|
|
|
25
|
+
function normalizeHeaders (headers) {
|
|
26
|
+
if (!headers) {
|
|
27
|
+
return headers
|
|
28
|
+
}
|
|
29
|
+
if (typeof headers.forEach === 'function') {
|
|
30
|
+
const result = {}
|
|
31
|
+
headers.forEach((value, key) => {
|
|
32
|
+
result[key] = value
|
|
33
|
+
})
|
|
34
|
+
return result
|
|
35
|
+
}
|
|
36
|
+
return headers
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class ActivityPubClientError extends Error {
|
|
40
|
+
constructor (status, message, { url, method, headers, body } = {}) {
|
|
41
|
+
super(message)
|
|
42
|
+
this.name = 'ActivityPubClientError'
|
|
43
|
+
this.status = status
|
|
44
|
+
this.url = url
|
|
45
|
+
this.method = method
|
|
46
|
+
this.headers = normalizeHeaders(headers)
|
|
47
|
+
this.body = body
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
26
51
|
export class ActivityPubClient {
|
|
27
52
|
static #githubUrl = 'https://github.com/evanp/activitypub-bot'
|
|
28
53
|
static #userAgent = `activitypub.bot/${version} (${ActivityPubClient.#githubUrl})`
|
|
@@ -188,10 +213,10 @@ export class ActivityPubClient {
|
|
|
188
213
|
{ status: res.status, body, url: baseUrl },
|
|
189
214
|
'Could not fetch url'
|
|
190
215
|
)
|
|
191
|
-
throw new
|
|
192
|
-
|
|
216
|
+
throw new ActivityPubClientError(
|
|
217
|
+
res.status,
|
|
193
218
|
`Could not fetch ${baseUrl}`,
|
|
194
|
-
{ headers: res.headers }
|
|
219
|
+
{ url: baseUrl, method, headers: res.headers, body }
|
|
195
220
|
)
|
|
196
221
|
}
|
|
197
222
|
|
|
@@ -297,10 +322,10 @@ export class ActivityPubClient {
|
|
|
297
322
|
await this.#limiter.update(hostname, res.headers)
|
|
298
323
|
this.#logger.debug({ url }, 'Done fetching POST')
|
|
299
324
|
if (res.status < 200 || res.status > 299) {
|
|
300
|
-
throw new
|
|
301
|
-
|
|
325
|
+
throw new ActivityPubClientError(
|
|
326
|
+
res.status,
|
|
302
327
|
`Could not post to ${url}`,
|
|
303
|
-
{ headers: res.headers }
|
|
328
|
+
{ url, method, headers: res.headers }
|
|
304
329
|
)
|
|
305
330
|
}
|
|
306
331
|
if (!storedPolicy && lastPolicy) {
|
package/lib/app.js
CHANGED
|
@@ -9,7 +9,7 @@ import Logger from 'pino'
|
|
|
9
9
|
import HTTPLogger from 'pino-http'
|
|
10
10
|
|
|
11
11
|
import { ActivityDistributor } from './activitydistributor.js'
|
|
12
|
-
import { ActivityPubClient } from './activitypubclient.js'
|
|
12
|
+
import { ActivityPubClient, ActivityPubClientError } from './activitypubclient.js'
|
|
13
13
|
import { ActorStorage } from './actorstorage.js'
|
|
14
14
|
import { BotDataStorage } from './botdatastorage.js'
|
|
15
15
|
import { KeyStorage } from './keystorage.js'
|
|
@@ -255,31 +255,46 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
255
255
|
|
|
256
256
|
app.use((err, req, res, next) => {
|
|
257
257
|
const { logger } = req.app.locals
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
258
|
+
if (err instanceof ActivityPubClientError) {
|
|
259
|
+
logger.error({
|
|
260
|
+
err,
|
|
261
|
+
status: err.status,
|
|
262
|
+
url: err.url,
|
|
263
|
+
method: err.method
|
|
264
|
+
}, 'ActivityPub client request failed')
|
|
265
|
+
res.status(500).type('application/problem+json').json({
|
|
266
|
+
type: 'about:blank',
|
|
267
|
+
title: 'Internal Server Error',
|
|
268
|
+
status: 500,
|
|
269
|
+
detail: 'Internal Server Error'
|
|
270
|
+
})
|
|
270
271
|
} else {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
272
|
+
let status = 500
|
|
273
|
+
if (err.status) {
|
|
274
|
+
status = err.status
|
|
275
|
+
}
|
|
276
|
+
const title = (http.STATUS_CODES[status])
|
|
277
|
+
? http.STATUS_CODES[status]
|
|
278
|
+
: 'Unknown Status'
|
|
279
|
+
|
|
280
|
+
if (status >= 500 && status < 600) {
|
|
281
|
+
logger.error(err)
|
|
282
|
+
} else if (status >= 400 && status < 500) {
|
|
283
|
+
logger.warn(err)
|
|
284
|
+
} else {
|
|
285
|
+
logger.debug(err)
|
|
286
|
+
}
|
|
287
|
+
const type = err.type || 'about:blank'
|
|
288
|
+
const problemTitle = err.title || title
|
|
289
|
+
const extra = Object.fromEntries(
|
|
290
|
+
Object.entries(err).filter(
|
|
291
|
+
([k]) => !['status', 'type', 'title', 'detail', 'stack'].includes(k)
|
|
292
|
+
)
|
|
278
293
|
)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
res.status(status)
|
|
295
|
+
res.type('application/problem+json')
|
|
296
|
+
res.json({ type, title: problemTitle, status, detail: err.message, ...extra })
|
|
297
|
+
}
|
|
283
298
|
})
|
|
284
299
|
|
|
285
300
|
app.onIdle = async () => {
|
package/lib/ratelimiter.js
CHANGED
|
@@ -11,7 +11,7 @@ export class RateLimiter {
|
|
|
11
11
|
assert.strictEqual(typeof connection, 'object')
|
|
12
12
|
assert.strictEqual(typeof logger, 'object')
|
|
13
13
|
this.#connection = connection
|
|
14
|
-
this.#logger = logger
|
|
14
|
+
this.#logger = logger.child({ class: this.constructor.name })
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
async limit (host, maxWaitTime = 30000) {
|
package/lib/remoteobjectcache.js
CHANGED
|
@@ -18,7 +18,7 @@ export class SignaturePolicyStorage {
|
|
|
18
18
|
assert.ok(logger)
|
|
19
19
|
assert.strictEqual(typeof logger, 'object')
|
|
20
20
|
this.#connection = connection
|
|
21
|
-
this.#logger = logger
|
|
21
|
+
this.#logger = logger.child({ class: this.constructor.name })
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
async get (origin) {
|