1+ const { expect } = require ( 'chai' ) ;
2+ const sinon = require ( 'sinon' ) ;
3+ const { PassThrough } = require ( 'stream' ) ;
4+ const proxyquire = require ( 'proxyquire' ) . noCallThru ( ) ;
5+
6+ const fakeRawBody = sinon . stub ( ) . resolves ( Buffer . from ( 'payload' ) ) ;
7+
8+ const fakeChain = {
9+ executeChain : sinon . stub ( ) ,
10+ } ;
11+
12+ const { teeAndValidate, isPackPost, handleMessage } = proxyquire ( '../src/proxy/routes' , {
13+ 'raw-body' : fakeRawBody ,
14+ '../chain' : fakeChain ,
15+ } ) ;
16+
17+ describe ( 'teeAndValidate middleware' , ( ) => {
18+ let req ;
19+ let res ;
20+ let next ;
21+
22+ beforeEach ( ( ) => {
23+ req = new PassThrough ( ) ;
24+ req . method = 'POST' ;
25+ req . url = '/proj/foo.git/git-upload-pack' ;
26+
27+ res = {
28+ set : sinon . stub ( ) . returnsThis ( ) ,
29+ status : sinon . stub ( ) . returnsThis ( ) ,
30+ send : sinon . stub ( ) ,
31+ end : sinon . stub ( ) ,
32+ } ;
33+ next = sinon . spy ( ) ;
34+
35+ fakeRawBody . resetHistory ( ) ;
36+ fakeChain . executeChain . resetHistory ( ) ;
37+ } ) ;
38+
39+ it . only ( 'skips non-pack posts' , async ( ) => {
40+ req . method = 'GET' ;
41+ await teeAndValidate ( req , res , next ) ;
42+ expect ( next . calledOnce ) . to . be . true ;
43+ expect ( fakeRawBody . called ) . to . be . false ;
44+ } ) ;
45+
46+ it . only ( '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 ;
60+ expect ( res . send . calledWith ( handleMessage ( 'denied!' ) ) ) . to . be . true ;
61+ } ) ;
62+
63+ it . only ( 'when the chain allow it calls next() and overrides req.pipe' , async ( ) => {
64+ fakeChain . executeChain . resolves ( { blocked : false , error : false } ) ;
65+
66+ req . write ( 'abcd' ) ;
67+ req . end ( ) ;
68+
69+ await teeAndValidate ( req , res , next ) ;
70+
71+ expect ( fakeRawBody . calledOnce ) . to . be . true ;
72+ expect ( fakeChain . executeChain . calledOnce ) . to . be . true ;
73+ expect ( next . calledOnce ) . to . be . true ;
74+ expect ( typeof req . pipe ) . to . equal ( 'function' ) ;
75+ } ) ;
76+ } ) ;
77+
78+ describe ( 'isPackPost()' , ( ) => {
79+ it . only ( 'returns true for git-upload-pack POST' , ( ) => {
80+ expect ( isPackPost ( { method : 'POST' , url : '/a/b.git/git-upload-pack' } ) ) . to . be . true ;
81+ } ) ;
82+ it . only ( 'returns false for other URLs' , ( ) => {
83+ expect ( isPackPost ( { method : 'POST' , url : '/info/refs' } ) ) . to . be . false ;
84+ } ) ;
85+ } ) ;
0 commit comments