9
9
using Microsoft . Extensions . DependencyInjection . Extensions ;
10
10
using Microsoft . Extensions . Logging ;
11
11
using System . CommandLine . Builder ;
12
+ using System . CommandLine . Invocation ;
12
13
using System . CommandLine . IO ;
13
14
using System . Text . Encodings . Web ;
14
15
using System . Text . Json ;
@@ -27,15 +28,13 @@ public static class Helpers
27
28
HttpMethod . Delete . Method ,
28
29
HttpMethod . Options . Method
29
30
} ;
30
-
31
+
31
32
public static readonly JsonSerializerOptions JsonSerializerOptions = new ( )
32
33
{
33
34
WriteIndented = true ,
34
35
Encoder = JavaScriptEncoder . UnsafeRelaxedJsonEscaping
35
36
} ;
36
37
37
- private static readonly HashSet < Option > SupportedOptions = new ( ) ;
38
-
39
38
private static IServiceCollection AddHttpHandlerMiddleware < THttpHandlerMiddleware > (
40
39
this IServiceCollection serviceCollection )
41
40
where THttpHandlerMiddleware : IHttpHandlerMiddleware
@@ -63,26 +62,11 @@ private static IServiceCollection AddResponseMiddleware<TResponseMiddleware>(
63
62
return serviceCollection ;
64
63
}
65
64
66
- public static void InitializeSupportOptions ( IServiceProvider serviceProvider )
65
+ private static Parser ConstructCommand ( this IServiceProvider serviceProvider , Func < InvocationContext , Task > ? handler = null )
67
66
{
68
- if ( SupportedOptions . Count == 0 )
69
- {
70
- foreach ( var option in
71
- serviceProvider
72
- . GetServices < IHttpHandlerMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) )
73
- . Union ( serviceProvider . GetServices < IRequestMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) )
74
- . Union ( serviceProvider . GetServices < IResponseMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) ) )
75
- . Union ( serviceProvider . GetRequiredService < IOutputFormatter > ( ) . SupportedOptions ( ) )
76
- . Union ( serviceProvider . GetRequiredService < IRequestExecutor > ( ) . SupportedOptions ( ) ) )
77
- . Union ( serviceProvider . GetRequiredService < ILoadTestExporterSelector > ( ) . SupportedOptions ( ) )
78
- . Union ( serviceProvider . GetServices < ILoadTestExporter > ( ) . SelectMany ( x => x . SupportedOptions ( ) ) )
79
- )
80
- {
81
- SupportedOptions . Add ( option ) ;
82
- }
83
- }
84
- var command = InitializeCommand ( ) ;
67
+ var command = InitializeCommandInternal ( serviceProvider , handler ) ;
85
68
var builder = new CommandLineBuilder ( command ) ;
69
+ // builder.UseDefaults();
86
70
builder
87
71
. UseHelp ( "--help" , "-?" , "/?" )
88
72
. UseEnvironmentVariableDirective ( )
@@ -95,54 +79,93 @@ public static void InitializeSupportOptions(IServiceProvider serviceProvider)
95
79
. CancelOnProcessTermination ( )
96
80
. AddMiddleware ( async ( invocationContext , next ) =>
97
81
{
98
- var context = DependencyResolver . ResolveRequiredService < HttpContext > ( ) ;
99
- context . CancellationToken = invocationContext . GetCancellationToken ( ) ;
100
- await DependencyResolver . ResolveRequiredService < IRequestExecutor > ( )
101
- . ExecuteAsync ( context ) ;
102
- var output = await DependencyResolver . ResolveRequiredService < IOutputFormatter > ( )
103
- . GetOutput ( context ) ;
104
- invocationContext . Console . Out . WriteLine ( output . Trim ( ) ) ;
105
-
82
+ var context = serviceProvider . GetRequiredService < HttpContext > ( ) ;
83
+ context . InvocationContext = invocationContext ;
84
+
85
+ var requestModel = context . Request ;
86
+ requestModel . ParseResult = invocationContext . ParseResult ;
87
+
88
+ var method = requestModel . ParseResult . UnmatchedTokens
89
+ . FirstOrDefault ( x => HttpMethods . Contains ( x ) ) ;
90
+ if ( ! string . IsNullOrEmpty ( method ) )
91
+ {
92
+ requestModel . Method = new HttpMethod ( method ) ;
93
+ }
94
+ // Url
95
+ requestModel . Url = requestModel . ParseResult . UnmatchedTokens . FirstOrDefault ( x =>
96
+ ! x . StartsWith ( "-" , StringComparison . Ordinal )
97
+ && ! HttpMethods . Contains ( x ) )
98
+ ?? string . Empty ;
99
+ if ( string . IsNullOrEmpty ( requestModel . Url ) )
100
+ {
101
+ throw new InvalidOperationException ( "The request url can not be null" ) ;
102
+ }
103
+ requestModel . RequestItems = requestModel . ParseResult . UnmatchedTokens
104
+ . Except ( new [ ] { method , requestModel . Url } )
105
+ . WhereNotNull ( )
106
+ . Where ( x => ! x . StartsWith ( '-' ) )
107
+ . ToArray ( ) ;
108
+
106
109
await next ( invocationContext ) ;
107
- } ) ;
108
- _commandParser = builder . Build ( ) ;
110
+ } )
111
+ ;
112
+ return builder . Build ( ) ;
109
113
}
110
114
111
- private static Parser _commandParser = null ! ;
112
-
113
- private static Command InitializeCommand ( )
115
+ private static Command InitializeCommandInternal ( IServiceProvider serviceProvider , Func < InvocationContext , Task > ? handler = null )
114
116
{
115
117
var command = new RootCommand ( )
116
118
{
117
119
Name = "http" ,
118
120
} ;
119
- //var methodArgument = new Argument<HttpMethod>("method")
120
- //{
121
- // Description = "Request method",
122
- // Arity = ArgumentArity.ZeroOrOne,
123
- //};
124
- //methodArgument.SetDefaultValue(HttpMethod.Get.Method);
125
- //var allowedMethods = HttpMethods.ToArray();
126
- //methodArgument.AddSuggestions(allowedMethods);
127
-
128
- //command.AddArgument(methodArgument);
129
- //var urlArgument = new Argument<string>("url")
130
- //{
131
- // Description = "Request url",
132
- // Arity = ArgumentArity.ExactlyOne
133
- //};
134
- //command.AddArgument(urlArgument);
135
-
136
- foreach ( var option in SupportedOptions )
121
+
122
+ // var methodArgument = new Argument<HttpMethod>("method")
123
+ // {
124
+ // Description = "Request method",
125
+ // Arity = ArgumentArity.ZeroOrOne,
126
+ // };
127
+ // methodArgument.SetDefaultValue(HttpMethod.Get.Method);
128
+ // var allowedMethods = HttpMethods.ToArray();
129
+ // methodArgument.AddCompletions(allowedMethods);
130
+ // command.AddArgument(methodArgument);
131
+
132
+ // var urlArgument = new Argument<string>("url")
133
+ // {
134
+ // Description = "Request url",
135
+ // Arity = ArgumentArity.ExactlyOne
136
+ // };
137
+ // command.AddArgument(urlArgument);
138
+
139
+ // options
140
+ foreach ( var option in
141
+ serviceProvider
142
+ . GetServices < IHttpHandlerMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) )
143
+ . Union ( serviceProvider . GetServices < IRequestMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) )
144
+ . Union ( serviceProvider . GetServices < IResponseMiddleware > ( ) . SelectMany ( x => x . SupportedOptions ( ) ) )
145
+ . Union ( serviceProvider . GetRequiredService < IOutputFormatter > ( ) . SupportedOptions ( ) )
146
+ . Union ( serviceProvider . GetRequiredService < IRequestExecutor > ( ) . SupportedOptions ( ) ) )
147
+ . Union ( serviceProvider . GetRequiredService < ILoadTestExporterSelector > ( ) . SupportedOptions ( ) )
148
+ . Union ( serviceProvider . GetServices < ILoadTestExporter > ( ) . SelectMany ( x => x . SupportedOptions ( ) ) )
149
+ )
137
150
{
138
151
command . AddOption ( option ) ;
139
152
}
140
153
command . TreatUnmatchedTokensAsErrors = false ;
154
+
155
+ handler ??= async invocationContext =>
156
+ {
157
+ var context = serviceProvider . ResolveRequiredService < HttpContext > ( ) ;
158
+ await serviceProvider . ResolveRequiredService < IRequestExecutor > ( )
159
+ . ExecuteAsync ( context ) ;
160
+ var output = await serviceProvider . ResolveRequiredService < IOutputFormatter > ( )
161
+ . GetOutput ( context ) ;
162
+ invocationContext . Console . Out . WriteLine ( output . Trim ( ) ) ;
163
+ } ;
164
+ command . SetHandler ( handler ) ;
141
165
return command ;
142
166
}
143
-
144
- // ReSharper disable once InconsistentNaming
145
- public static IServiceCollection RegisterHTTPieServices ( this IServiceCollection serviceCollection )
167
+
168
+ public static IServiceCollection RegisterApplicationServices ( this IServiceCollection serviceCollection )
146
169
{
147
170
serviceCollection
148
171
. AddSingleton < IRequestExecutor , RequestExecutor > ( )
@@ -207,54 +230,16 @@ public static IServiceCollection RegisterHTTPieServices(this IServiceCollection
207
230
. AddResponseMiddleware < JsonSchemaValidationMiddleware > ( )
208
231
;
209
232
}
210
-
211
- public static void InitRequestModel ( HttpContext httpContext , string commandLine )
212
- => InitRequestModel ( httpContext , CommandLineStringSplitter . Instance . Split ( commandLine ) . ToArray ( ) ) ;
213
-
214
- public static void InitRequestModel ( HttpContext httpContext , string [ ] args )
215
- {
216
- // should output helps
217
- if ( args . Contains ( "-?" ) || args . Contains ( "--help" ) )
218
- {
219
- return ;
220
- }
221
- var requestModel = httpContext . Request ;
222
- requestModel . ParseResult = _commandParser . Parse ( args ) ;
223
-
224
- var method = requestModel . ParseResult . UnmatchedTokens . FirstOrDefault ( x => HttpMethods . Contains ( x ) ) ;
225
- if ( ! string . IsNullOrEmpty ( method ) )
226
- {
227
- requestModel . Method = new HttpMethod ( method ) ;
228
- }
229
- // Url
230
- requestModel . Url = requestModel . ParseResult . UnmatchedTokens . FirstOrDefault ( x =>
231
- ! x . StartsWith ( "-" , StringComparison . Ordinal )
232
- && ! HttpMethods . Contains ( x ) )
233
- ?? string . Empty ;
234
- if ( string . IsNullOrEmpty ( requestModel . Url ) )
235
- {
236
- throw new InvalidOperationException ( "The request url can not be null" ) ;
237
- }
238
- requestModel . Options = args
239
- . Where ( x => x . StartsWith ( '-' ) )
240
- . ToArray ( ) ;
241
- #nullable disable
242
- requestModel . RequestItems = requestModel . ParseResult . UnmatchedTokens
243
- . Except ( new [ ] { method , requestModel . Url } )
244
- . Where ( x => ! x . StartsWith ( '-' ) )
245
- . ToArray ( ) ;
246
- #nullable restore
247
- }
248
-
233
+
249
234
public static async Task < int > Handle ( this IServiceProvider services , string [ ] args )
250
235
{
251
- InitRequestModel ( services . GetRequiredService < HttpContext > ( ) , args ) ;
252
- return await _commandParser . InvokeAsync ( args ) ;
236
+ var commandParser = services . ConstructCommand ( ) ;
237
+ return await commandParser . InvokeAsync ( args ) ;
253
238
}
254
-
255
- public static async Task < int > Handle ( this IServiceProvider services , string commandLine )
239
+
240
+ public static async Task < int > Handle ( this IServiceProvider services , string commandLine , Func < InvocationContext , Task > ? handler = null )
256
241
{
257
- InitRequestModel ( services . GetRequiredService < HttpContext > ( ) , commandLine ) ;
258
- return await _commandParser . InvokeAsync ( commandLine ) ;
242
+ var commandParser = services . ConstructCommand ( handler ) ;
243
+ return await commandParser . InvokeAsync ( commandLine ) ;
259
244
}
260
245
}
0 commit comments