Skip to content

Commit 6f17fec

Browse files
authored
Merge branch 'main' into fix-linter-warnings
2 parents e40a30e + dcf154f commit 6f17fec

File tree

2 files changed

+25
-54
lines changed

2 files changed

+25
-54
lines changed

src/proxy/routes/index.ts

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ const proxyFilter: ProxyOptions['filter'] = async (req, res) => {
4545
return false;
4646
}
4747

48+
// For POST pack requests, use the raw body extracted by extractRawBody middleware
49+
if (isPackPost(req) && (req as any).bodyRaw) {
50+
(req as any).body = (req as any).bodyRaw;
51+
// Clean up the bodyRaw property before forwarding the request
52+
delete (req as any).bodyRaw;
53+
}
54+
4855
const action = await executeChain(req, res);
4956

5057
if (action.error || action.blocked) {
@@ -128,7 +135,7 @@ const proxyReqBodyDecorator: ProxyOptions['proxyReqBodyDecorator'] = (bodyConten
128135
return bodyContent;
129136
};
130137

131-
const proxyErrorHandler: ProxyOptions['proxyErrorHandler'] = (err, res, next) => {
138+
const proxyErrorHandler: ProxyOptions['proxyErrorHandler'] = (err, _res, next) => {
132139
console.log(`ERROR=${err}`);
133140
next(err);
134141
};
@@ -137,42 +144,24 @@ const isPackPost = (req: Request) =>
137144
req.method === 'POST' &&
138145
/^(?:\/[^/]+)*\/[^/]+\.git\/(?:git-upload-pack|git-receive-pack)$/.test(req.url);
139146

140-
const teeAndValidate = async (req: Request, res: Response, next: NextFunction) => {
147+
const extractRawBody = async (req: Request, res: Response, next: NextFunction) => {
141148
if (!isPackPost(req)) {
142149
return next();
143150
}
144151

145-
const proxyStream = new PassThrough();
146-
const pluginStream = new PassThrough();
152+
const proxyStream = new PassThrough({
153+
highWaterMark: 4 * 1024 * 1024,
154+
});
155+
const pluginStream = new PassThrough({
156+
highWaterMark: 4 * 1024 * 1024,
157+
});
147158

148159
req.pipe(proxyStream);
149160
req.pipe(pluginStream);
150161

151162
try {
152163
const buf = await getRawBody(pluginStream, { limit: '1gb' });
153-
(req as any).body = buf;
154-
const verdict = await executeChain(req, res);
155-
if (verdict.error || verdict.blocked) {
156-
const message = verdict.errorMessage ?? verdict.blockedMessage ?? 'Unknown error';
157-
const type = verdict.error ? ActionType.ERROR : ActionType.BLOCKED;
158-
159-
logAction(req.url, req.headers?.host, req.headers?.['user-agent'], type, message);
160-
161-
res
162-
.set({
163-
'content-type': 'application/x-git-receive-pack-result',
164-
expires: 'Fri, 01 Jan 1980 00:00:00 GMT',
165-
pragma: 'no-cache',
166-
'cache-control': 'no-cache, max-age=0, must-revalidate',
167-
vary: 'Accept-Encoding',
168-
'x-frame-options': 'DENY',
169-
connection: 'close',
170-
})
171-
.status(200) // return status 200 to ensure that the error message is rendered by the git client
172-
.send(handleMessage(message));
173-
return;
174-
}
175-
164+
(req as any).bodyRaw = buf;
176165
(req as any).pipe = (dest: any, opts: any) => proxyStream.pipe(dest, opts);
177166
next();
178167
} catch (e) {
@@ -184,7 +173,7 @@ const teeAndValidate = async (req: Request, res: Response, next: NextFunction) =
184173

185174
const getRouter = async () => {
186175
const router = Router();
187-
router.use(teeAndValidate);
176+
router.use(extractRawBody);
188177

189178
const originsToProxy = await getAllProxiedHosts();
190179
const proxyKeys: string[] = [];
@@ -259,6 +248,6 @@ export {
259248
handleMessage,
260249
handleRefsErrorMessage,
261250
isPackPost,
262-
teeAndValidate,
251+
extractRawBody,
263252
validGitRequest,
264253
};
Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ const fakeChain = {
99
executeChain: sinon.stub(),
1010
};
1111

12-
const { teeAndValidate, isPackPost, handleMessage } = proxyquire('../src/proxy/routes', {
12+
const { extractRawBody, isPackPost } = proxyquire('../src/proxy/routes', {
1313
'raw-body': fakeRawBody,
1414
'../chain': fakeChain,
1515
});
1616

17-
describe('teeAndValidate middleware', () => {
17+
describe('extractRawBody middleware', () => {
1818
let req;
1919
let res;
2020
let next;
@@ -38,39 +38,21 @@ describe('teeAndValidate middleware', () => {
3838

3939
it('skips non-pack posts', async () => {
4040
req.method = 'GET';
41-
await teeAndValidate(req, res, next);
41+
await extractRawBody(req, res, next);
4242
expect(next.calledOnce).to.be.true;
4343
expect(fakeRawBody.called).to.be.false;
4444
});
4545

46-
it('when the chain blocks it sends a packet and does NOT call next()', async () => {
47-
fakeChain.executeChain.resolves({ blocked: true, blockedMessage: 'denied!' });
48-
49-
req.write('abcd');
50-
req.end();
51-
52-
await teeAndValidate(req, res, next);
53-
54-
expect(fakeRawBody.calledOnce).to.be.true;
55-
expect(fakeChain.executeChain.calledOnce).to.be.true;
56-
expect(next.called).to.be.false;
57-
58-
expect(res.set.called).to.be.true;
59-
expect(res.status.calledWith(200)).to.be.true; // status 200 is used to ensure error message is rendered by git client
60-
expect(res.send.calledWith(handleMessage('denied!'))).to.be.true;
61-
});
62-
63-
it('when the chain allow it calls next() and overrides req.pipe', async () => {
64-
fakeChain.executeChain.resolves({ blocked: false, error: false });
65-
46+
it('extracts raw body and sets bodyRaw property', async () => {
6647
req.write('abcd');
6748
req.end();
6849

69-
await teeAndValidate(req, res, next);
50+
await extractRawBody(req, res, next);
7051

7152
expect(fakeRawBody.calledOnce).to.be.true;
72-
expect(fakeChain.executeChain.calledOnce).to.be.true;
53+
expect(fakeChain.executeChain.called).to.be.false;
7354
expect(next.calledOnce).to.be.true;
55+
expect(req.bodyRaw).to.exist;
7456
expect(typeof req.pipe).to.equal('function');
7557
});
7658
});

0 commit comments

Comments
 (0)