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