enhance(backend): headタグ内にrel=alternateの指定のあるlinkタグがある場合、記述されたURLを参照して照会できるように (#14371)
* signedGet時にhttpかつalternate属性のlinkがある場合に一回だけfollowして照会する * Fix: validation position * Fix import * Fix tagname * Update CHANGELOG * Fix code style --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									fd744f44c1
								
							
						
					
					
						commit
						9fbc1b7f7b
					
				
					 2 changed files with 23 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
import * as crypto from 'node:crypto';
 | 
			
		||||
import { URL } from 'node:url';
 | 
			
		||||
import { Inject, Injectable } from '@nestjs/common';
 | 
			
		||||
import { Window } from 'happy-dom';
 | 
			
		||||
import { DI } from '@/di-symbols.js';
 | 
			
		||||
import type { Config } from '@/config.js';
 | 
			
		||||
import type { MiUser } from '@/models/User.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +181,8 @@ export class ApRequestService {
 | 
			
		|||
	 * @param url URL to fetch
 | 
			
		||||
	 */
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public async signedGet(url: string, user: { id: MiUser['id'] }): Promise<unknown> {
 | 
			
		||||
	public async signedGet(url: string, user: { id: MiUser['id'] }, followAlternate?: boolean): Promise<unknown> {
 | 
			
		||||
		const _followAlternate = followAlternate ?? true;
 | 
			
		||||
		const keypair = await this.userKeypairService.getUserKeypair(user.id);
 | 
			
		||||
 | 
			
		||||
		const req = ApRequestCreator.createSignedGet({
 | 
			
		||||
| 
						 | 
				
			
			@ -198,9 +200,27 @@ export class ApRequestService {
 | 
			
		|||
			headers: req.request.headers,
 | 
			
		||||
		}, {
 | 
			
		||||
			throwErrorWhenResponseNotOk: true,
 | 
			
		||||
			validators: [validateContentTypeSetAsActivityPub],
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		//#region リクエスト先がhtmlかつactivity+jsonへのalternate linkタグがあるとき
 | 
			
		||||
		if (res.headers.get('Content-type')?.startsWith('text/html;') && _followAlternate === true) {
 | 
			
		||||
			const html = await res.text();
 | 
			
		||||
			const window = new Window();
 | 
			
		||||
			const document = window.document;
 | 
			
		||||
			document.documentElement.innerHTML = html;
 | 
			
		||||
 | 
			
		||||
			const alternate = document.querySelector('head > link[rel="alternate"][type="application/activity+json"]');
 | 
			
		||||
			if (alternate) {
 | 
			
		||||
				const href = alternate.getAttribute('href');
 | 
			
		||||
				if (href) {
 | 
			
		||||
					return await this.signedGet(href, user, false);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		//#endregion
 | 
			
		||||
 | 
			
		||||
		validateContentTypeSetAsActivityPub(res);
 | 
			
		||||
 | 
			
		||||
		return await res.json();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue