Merge pull request #6533 from mempool/mononaut/fix-proxies

This commit is contained in:
wiz 2026-05-30 10:32:59 +09:00 committed by GitHub
commit d26d14dd62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 16 deletions

View file

@ -3,6 +3,8 @@ import config from '../config';
import axios from 'axios';
import logger from '../logger';
const PROXY_PATH_SEGMENT_REGEX = /^(?!\.{1,2}$)[^\p{Cc}/?#\\]{1,256}$/u;
class AboutRoutes {
public initRoutes(app: Application) {
app
@ -15,8 +17,13 @@ class AboutRoutes {
}
})
.get(config.MEMPOOL.API_URL_PREFIX + 'donations/images/:id', async (req, res) => {
if (!PROXY_PATH_SEGMENT_REGEX.test(req.params.id)) {
res.status(400).end();
return;
}
try {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/donations/images/${req.params.id}`, {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/donations/images/${encodeURIComponent(req.params.id)}`, {
responseType: 'stream', timeout: 10000
});
response.data.pipe(res);
@ -33,8 +40,13 @@ class AboutRoutes {
}
})
.get(config.MEMPOOL.API_URL_PREFIX + 'contributors/images/:id', async (req, res) => {
if (!PROXY_PATH_SEGMENT_REGEX.test(req.params.id)) {
res.status(400).end();
return;
}
try {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/contributors/images/${req.params.id}`, {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/contributors/images/${encodeURIComponent(req.params.id)}`, {
responseType: 'stream', timeout: 10000
});
response.data.pipe(res);
@ -51,8 +63,13 @@ class AboutRoutes {
}
})
.get(config.MEMPOOL.API_URL_PREFIX + 'translators/images/:id', async (req, res) => {
if (!PROXY_PATH_SEGMENT_REGEX.test(req.params.id)) {
res.status(400).end();
return;
}
try {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/translators/images/${req.params.id}`, {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.MEMPOOL_API}/translators/images/${encodeURIComponent(req.params.id)}`, {
responseType: 'stream', timeout: 10000
});
response.data.pipe(res);
@ -61,7 +78,7 @@ class AboutRoutes {
}
})
.get(config.MEMPOOL.API_URL_PREFIX + 'services/sponsors', async (req, res) => {
const url = `${config.MEMPOOL_SERVICES.API}/${req.originalUrl.replace('/api/v1/services/', '')}`;
const url = `${config.MEMPOOL_SERVICES.API}/sponsors`;
try {
const response = await axios.get(url, { responseType: 'stream', timeout: 10000 });
response.data.pipe(res);
@ -71,7 +88,12 @@ class AboutRoutes {
}
})
.get(config.MEMPOOL.API_URL_PREFIX + 'services/account/images/:username/:md5', async (req, res) => {
const url = `${config.MEMPOOL_SERVICES.API}/${req.originalUrl.replace('/api/v1/services/', '')}`;
if (!PROXY_PATH_SEGMENT_REGEX.test(req.params.username) || !PROXY_PATH_SEGMENT_REGEX.test(req.params.md5)) {
res.status(400).end();
return;
}
const url = `${config.MEMPOOL_SERVICES.API}/account/images/${encodeURIComponent(req.params.username)}/${encodeURIComponent(req.params.md5)}`;
try {
const response = await axios.get(url, { responseType: 'stream', timeout: 10000 });
response.data.pipe(res);
@ -84,4 +106,4 @@ class AboutRoutes {
}
}
export default new AboutRoutes();
export default new AboutRoutes();

View file

@ -5,16 +5,18 @@ import logger from '../../logger';
import mempool from '../mempool';
import AccelerationRepository from '../../repositories/AccelerationRepository';
const TXID_REGEX = /^[a-f0-9]{64}$/i;
class AccelerationRoutes {
private tag = 'Accelerator';
public initRoutes(app: Application): void {
app
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations', this.$getAcceleratorAccelerations.bind(this))
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations/:txid', this.$getAcceleratorAcceleration.bind(this))
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations/history', this.$getAcceleratorAccelerationsHistory.bind(this))
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations/history/aggregated', this.$getAcceleratorAccelerationsHistoryAggregated.bind(this))
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations/stats', this.$getAcceleratorAccelerationsStats.bind(this))
.get(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/accelerations/:txid', this.$getAcceleratorAcceleration.bind(this))
.post(config.MEMPOOL.API_URL_PREFIX + 'services/accelerator/estimate', this.$getAcceleratorEstimate.bind(this))
;
}
@ -26,7 +28,7 @@ class AccelerationRoutes {
/** @asyncUnsafe */
private async $getAcceleratorAcceleration(req: Request, res: Response): Promise<void> {
if (req.params.txid) {
if (req.params.txid && TXID_REGEX.test(req.params.txid)) {
const acceleration = await AccelerationRepository.$getAccelerationInfoForTxid(req.params.txid);
if (acceleration) {
res.status(200).send(acceleration);
@ -34,7 +36,7 @@ class AccelerationRoutes {
res.status(404).send('Acceleration not found');
}
} else {
res.status(400).send('txid is required');
res.status(400).send('invalid txid');
}
}
@ -55,9 +57,9 @@ class AccelerationRoutes {
}
private async $getAcceleratorAccelerationsHistoryAggregated(req: Request, res: Response): Promise<void> {
const url = `${config.MEMPOOL_SERVICES.API}/${req.originalUrl.replace('/api/v1/services/', '')}`;
const url = `${config.MEMPOOL_SERVICES.API}/accelerator/accelerations/history/aggregated`;
try {
const response = await axios.get(url, { responseType: 'stream', timeout: 10000 });
const response = await axios.get(url, { params: req.query, responseType: 'stream', timeout: 10000 });
for (const key in response.headers) {
res.setHeader(key, response.headers[key]);
}
@ -69,9 +71,9 @@ class AccelerationRoutes {
}
private async $getAcceleratorAccelerationsStats(req: Request, res: Response): Promise<void> {
const url = `${config.MEMPOOL_SERVICES.API}/${req.originalUrl.replace('/api/v1/services/', '')}`;
const url = `${config.MEMPOOL_SERVICES.API}/accelerator/accelerations/stats`;
try {
const response = await axios.get(url, { responseType: 'stream', timeout: 10000 });
const response = await axios.get(url, { params: req.query, responseType: 'stream', timeout: 10000 });
for (const key in response.headers) {
res.setHeader(key, response.headers[key]);
}
@ -83,7 +85,7 @@ class AccelerationRoutes {
}
private async $getAcceleratorEstimate(req: Request, res: Response): Promise<void> {
const url = `${config.MEMPOOL_SERVICES.API}/${req.originalUrl.replace('/api/v1/services/', '')}`;
const url = `${config.MEMPOOL_SERVICES.API}/accelerator/estimate`;
try {
const response = await axios.post(url, req.body, { responseType: 'stream', timeout: 10000 });
for (const key in response.headers) {
@ -97,4 +99,4 @@ class AccelerationRoutes {
}
}
export default new AccelerationRoutes();
export default new AccelerationRoutes();

View file

@ -6,6 +6,8 @@ import icons from './icons';
import { handleError } from '../../utils/api';
import PricesRepository from '../../repositories/PricesRepository';
const PROXY_PATH_SEGMENT_REGEX = /^(?!\.{1,2}$)[^\p{Cc}/?#\\]{1,256}$/u;
class LiquidRoutes {
public initRoutes(app: Application) {
app
@ -68,8 +70,13 @@ class LiquidRoutes {
}
private async $getAssetGroup(req: Request, res: Response) {
if (!PROXY_PATH_SEGMENT_REGEX.test(req.params.id)) {
handleError(req, res, 400, 'Invalid asset group id');
return;
}
try {
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.LIQUID_API}/assets/group/${parseInt(req.params.id, 10)}`,
const response = await axios.get(`${config.EXTERNAL_DATA_SERVER.LIQUID_API}/assets/group/${encodeURIComponent(req.params.id)}`,
{ responseType: 'stream', timeout: 10000 });
response.data.pipe(res);
} catch (e) {