@@ -114,93 +114,94 @@ func main() {
114
114
scanopts .OutputContentType = options .OutputContentType
115
115
scanopts .RequestBody = options .RequestBody
116
116
scanopts .Unsafe = options .Unsafe
117
+ scanopts .Pipeline = options .Pipeline
117
118
scanopts .HTTP2Probe = options .HTTP2Probe
118
119
scanopts .OutputMethod = options .OutputMethod
119
120
if len (scanopts .Methods ) > 0 {
120
121
scanopts .OutputMethod = true
121
- }
122
-
123
- // Try to create output folder if it doesnt exist
124
- if options .StoreResponse && ! fileutil .FolderExists (options .StoreResponseDir ) {
125
- if err := os .MkdirAll (options .StoreResponseDir , os .ModePerm ); err != nil {
126
- gologger .Fatalf ("Could not create output directory '%s': %s\n " , options .StoreResponseDir , err )
127
- }
128
- }
129
-
130
- // output routine
131
- wgoutput := sizedwaitgroup .New (1 )
132
- wgoutput .Add ()
133
- output := make (chan Result )
134
- go func (output chan Result ) {
135
- defer wgoutput .Done ()
136
122
137
- var f * os.File
138
- if options .Output != "" {
139
- var err error
140
- f , err = os .Create (options .Output )
141
- if err != nil {
142
- gologger .Fatalf ("Could not create output file '%s': %s\n " , options .Output , err )
123
+ // Try to create output folder if it doesnt exist
124
+ if options .StoreResponse && ! fileutil .FolderExists (options .StoreResponseDir ) {
125
+ if err := os .MkdirAll (options .StoreResponseDir , os .ModePerm ); err != nil {
126
+ gologger .Fatalf ("Could not create output directory '%s': %s\n " , options .StoreResponseDir , err )
143
127
}
144
- defer f .Close ()
145
128
}
146
- for r := range output {
147
- if r .err != nil {
148
- gologger .Debugf ("Failure '%s': %s\n " , r .URL , r .err )
149
- continue
150
- }
151
129
152
- // apply matchers and filters
153
- if len (options .filterStatusCode ) > 0 && slice .IntSliceContains (options .filterStatusCode , r .StatusCode ) {
154
- continue
155
- }
156
- if len (options .filterContentLength ) > 0 && slice .IntSliceContains (options .filterContentLength , r .ContentLength ) {
157
- continue
158
- }
159
- if len (options .matchStatusCode ) > 0 && ! slice .IntSliceContains (options .matchStatusCode , r .StatusCode ) {
160
- continue
130
+ // output routine
131
+ wgoutput := sizedwaitgroup .New (1 )
132
+ wgoutput .Add ()
133
+ output := make (chan Result )
134
+ go func (output chan Result ) {
135
+ defer wgoutput .Done ()
136
+
137
+ var f * os.File
138
+ if options .Output != "" {
139
+ var err error
140
+ f , err = os .Create (options .Output )
141
+ if err != nil {
142
+ gologger .Fatalf ("Could not create output file '%s': %s\n " , options .Output , err )
143
+ }
144
+ defer f .Close ()
161
145
}
162
- if len (options .matchContentLength ) > 0 && ! slice .IntSliceContains (options .matchContentLength , r .ContentLength ) {
163
- continue
146
+ for r := range output {
147
+ if r .err != nil {
148
+ gologger .Debugf ("Failure '%s': %s\n " , r .URL , r .err )
149
+ continue
150
+ }
151
+
152
+ // apply matchers and filters
153
+ if len (options .filterStatusCode ) > 0 && slice .IntSliceContains (options .filterStatusCode , r .StatusCode ) {
154
+ continue
155
+ }
156
+ if len (options .filterContentLength ) > 0 && slice .IntSliceContains (options .filterContentLength , r .ContentLength ) {
157
+ continue
158
+ }
159
+ if len (options .matchStatusCode ) > 0 && ! slice .IntSliceContains (options .matchStatusCode , r .StatusCode ) {
160
+ continue
161
+ }
162
+ if len (options .matchContentLength ) > 0 && ! slice .IntSliceContains (options .matchContentLength , r .ContentLength ) {
163
+ continue
164
+ }
165
+
166
+ row := r .str
167
+ if options .JSONOutput {
168
+ row = r .JSON ()
169
+ }
170
+
171
+ gologger .Silentf ("%s\n " , row )
172
+ if f != nil {
173
+ f .WriteString (row + "\n " )
174
+ }
164
175
}
176
+ }(output )
165
177
166
- row := r .str
167
- if options .JSONOutput {
168
- row = r .JSON ()
169
- }
178
+ wg := sizedwaitgroup .New (options .Threads )
179
+ var sc * bufio.Scanner
170
180
171
- gologger .Silentf ("%s\n " , row )
172
- if f != nil {
173
- f .WriteString (row + "\n " )
181
+ // check if file has been provided
182
+ if fileutil .FileExists (options .InputFile ) {
183
+ finput , err := os .Open (options .InputFile )
184
+ if err != nil {
185
+ gologger .Fatalf ("Could read input file '%s': %s\n " , options .InputFile , err )
174
186
}
187
+ defer finput .Close ()
188
+ sc = bufio .NewScanner (finput )
189
+ } else if fileutil .HasStdin () {
190
+ sc = bufio .NewScanner (os .Stdin )
191
+ } else {
192
+ gologger .Fatalf ("No input provided" )
175
193
}
176
- }(output )
177
-
178
- wg := sizedwaitgroup .New (options .Threads )
179
- var sc * bufio.Scanner
180
194
181
- // check if file has been provided
182
- if fileutil .FileExists (options .InputFile ) {
183
- finput , err := os .Open (options .InputFile )
184
- if err != nil {
185
- gologger .Fatalf ("Could read input file '%s': %s\n " , options .InputFile , err )
195
+ for sc .Scan () {
196
+ process (sc .Text (), & wg , hp , protocol , scanopts , output )
186
197
}
187
- defer finput .Close ()
188
- sc = bufio .NewScanner (finput )
189
- } else if fileutil .HasStdin () {
190
- sc = bufio .NewScanner (os .Stdin )
191
- } else {
192
- gologger .Fatalf ("No input provided" )
193
- }
194
-
195
- for sc .Scan () {
196
- process (sc .Text (), & wg , hp , protocol , scanopts , output )
197
- }
198
198
199
- wg .Wait ()
199
+ wg .Wait ()
200
200
201
- close (output )
201
+ close (output )
202
202
203
- wgoutput .Wait ()
203
+ wgoutput .Wait ()
204
+ }
204
205
}
205
206
206
207
func process (t string , wg * sizedwaitgroup.SizedWaitGroup , hp * httpx.HTTPX , protocol string , scanopts scanOptions , output chan Result ) {
@@ -310,6 +311,7 @@ type scanOptions struct {
310
311
OutputContentType bool
311
312
RequestBody string
312
313
Unsafe bool
314
+ Pipeline bool
313
315
HTTP2Probe bool
314
316
}
315
317
@@ -459,6 +461,14 @@ retry:
459
461
builder .WriteString (" [websocket]" )
460
462
}
461
463
464
+ pipeline := false
465
+ if scanopts .Pipeline {
466
+ pipeline = hp .SupportPipeline (protocol , method , domain , port )
467
+ if pipeline {
468
+ builder .WriteString (" [pipeline]" )
469
+ }
470
+ }
471
+
462
472
var http2 bool
463
473
// if requested probes for http2
464
474
if scanopts .HTTP2Probe {
@@ -496,6 +506,7 @@ retry:
496
506
WebSocket : isWebSocket ,
497
507
TlsData : resp .TlsData ,
498
508
CspData : resp .CspData ,
509
+ Pipeline : pipeline ,
499
510
HTTP2 : http2 ,
500
511
Method : method ,
501
512
}
@@ -518,6 +529,7 @@ type Result struct {
518
529
ContentType string `json:"content-type,omitempty"`
519
530
TlsData * httpx.TlsData `json:"tls,omitempty"`
520
531
CspData * httpx.CspData `json:"csp,omitempty"`
532
+ Pipeline bool `json:"pipeline,omitempty"`
521
533
HTTP2 bool `json:"http2"`
522
534
Method string `json:"method"`
523
535
}
@@ -579,6 +591,7 @@ type Options struct {
579
591
Unsafe bool
580
592
RequestBody string
581
593
Debug bool
594
+ Pipeline bool
582
595
HTTP2Probe bool
583
596
}
584
597
@@ -625,6 +638,7 @@ func ParseOptions() *Options {
625
638
flag .BoolVar (& options .Unsafe , "unsafe" , false , "Send raw requests skipping golang normalization" )
626
639
flag .StringVar (& options .RequestBody , "body" , "" , "Request Body" )
627
640
flag .BoolVar (& options .Debug , "debug" , false , "Debug mode" )
641
+ flag .BoolVar (& options .Pipeline , "pipeline" , false , "HTTP1.1 Pipeline" )
628
642
flag .BoolVar (& options .HTTP2Probe , "http2" , false , "HTTP2 probe" )
629
643
flag .Parse ()
630
644
0 commit comments