Proxy captions via new /proxy route
We can add more authorized paths to authorizedPaths if we need more resources to be pulled from the NewLeaf/Invidious backend on the same domain. This route forwards to the client a few headers like Bibliogram https://git.sr.ht/~cadence/bibliogram/tree/ea7cd5d5/item/src/site/api/proxy.js#L28-29 so we can also use this route to possibly proxy videos in the future. We are strict about the url parameter not overriding the NewLeaf/Invidious backend (instanceOrigin) by ensuring fetchURL has instanceOrigin as prefix.
This commit is contained in:
		
							parent
							
								
									db49bb38b0
								
							
						
					
					
						commit
						eb111a44c4
					
				| @ -1,27 +0,0 @@ | ||||
| /** @type {import("node-fetch").default} */ | ||||
| // @ts-ignore
 | ||||
| const fetch = require("node-fetch") | ||||
| const {getUser} = require("../utils/getuser") | ||||
| const constants = require("../utils/constants.js") | ||||
| 
 | ||||
| module.exports = [ | ||||
| 	{ | ||||
| 		route: `/api/v1/captions/(${constants.regex.video_id})`, methods: ["GET"], code: async ({req, fill, url}) => { | ||||
| 			const instanceOrigin = getUser(req).getSettingsOrDefaults().instance | ||||
| 			const fetchURL = new URL(`${url.pathname}${url.search}`, instanceOrigin) | ||||
| 			return fetch(fetchURL.toString()).then(res => { | ||||
| 				return res.text().then(text => { | ||||
| 					if (res.status === 200) { | ||||
| 						// Remove the position annotations that youtube unhelpfully provides
 | ||||
| 						text = text.replace(/(--> \S+).*/g, "$1") | ||||
| 					} | ||||
| 					return { | ||||
| 						statusCode: res.status, | ||||
| 						contentType: res.headers.get("content-type"), | ||||
| 						content: text | ||||
| 					} | ||||
| 				}) | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| ] | ||||
							
								
								
									
										27
									
								
								api/proxy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								api/proxy.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| const {proxy} = require("pinski/plugins") | ||||
| const {getUser} = require("../utils/getuser") | ||||
| const constants = require("../utils/constants.js") | ||||
| 
 | ||||
| // list of paths relative to the backend this route is authorized to serve
 | ||||
| const authorizedPaths = [`/api/v1/captions/(${constants.regex.video_id})`] | ||||
| 
 | ||||
| // headers relayed as-is from the proxied backend to the client
 | ||||
| const proxiedHeaders = ["content-type", "date", "last-modified", "expires", "cache-control", "accept-ranges", "content-range", "origin", "etag", "content-length", "transfer-encoding"] | ||||
| 
 | ||||
| module.exports = [ | ||||
| 	{ | ||||
| 		route: `/proxy`, methods: ["GET"], code: async ({req, fill, url}) => { | ||||
| 			const instanceOrigin = getUser(req).getSettingsOrDefaults().instance | ||||
| 			const remotePath = url.searchParams.get("url") | ||||
| 			const fetchURL = new URL(remotePath, instanceOrigin) | ||||
| 			if (!fetchURL.toString().startsWith(instanceOrigin) || !authorizedPaths.some(element => fetchURL.pathname.match(new RegExp(`^${element}$`)))) { | ||||
| 				return { | ||||
| 					statusCode: 401, | ||||
| 					content: "CloudTube: Unauthorized", | ||||
| 					contentType: "text/plain" | ||||
| 				} | ||||
| 			} | ||||
| 			return proxy(fetchURL, {}, (h) => Object.keys(h).filter(key => proxiedHeaders.includes(key)).reduce((res, key) => (res[key] = h[key], res), {})) | ||||
| 		} | ||||
| 	} | ||||
| ] | ||||
| @ -174,6 +174,11 @@ module.exports = [ | ||||
| 				// rewrite description
 | ||||
| 				video.descriptionHtml = converters.rewriteVideoDescription(video.descriptionHtml, id) | ||||
| 
 | ||||
| 				// rewrite captions urls so they are served on the same domain via the /proxy route
 | ||||
| 				for (const caption of video.captions) { | ||||
| 					caption.url = `/proxy?${new URLSearchParams({"url": caption.url})}` | ||||
| 				} | ||||
| 
 | ||||
| 				return render(200, "pug/video.pug", { | ||||
| 					url, video, formats, subscribed, instanceOrigin, mediaFragment, autoplay, continuous, | ||||
| 					sessionWatched, sessionWatchedNext | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user