protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { programState = programState ?? throw new ArgumentNullException(nameof(programState)); shellState = shellState ?? throw new ArgumentNullException(nameof(shellState)); commandInput = commandInput ?? throw new ArgumentNullException(nameof(commandInput)); if (programState.SwaggerEndpoint != null) { string swaggerRequeryBehaviorSetting = _preferences.GetValue(WellKnownPreference.SwaggerRequeryBehavior, "auto"); if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase)) { ApiConnection apiConnection = new ApiConnection(programState, _preferences, shellState.ConsoleManager, logVerboseMessages: false) { BaseUri = programState.BaseAddress, SwaggerUri = programState.SwaggerEndpoint, AllowBaseOverrideBySwagger = false }; await apiConnection.SetupHttpState(programState, performAutoDetect : false, cancellationToken).ConfigureAwait(false); } } if (programState.BaseAddress is null) { shellState.ConsoleManager.WriteLine(Resources.Strings.ListCommand_Error_NoBaseAddress.SetColor(programState.WarningColor)); return; } if (programState.SwaggerEndpoint is null || programState.Structure is null) { shellState.ConsoleManager.WriteLine(Resources.Strings.ListCommand_Error_NoDirectoryStructure.SetColor(programState.WarningColor)); return; } string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty; //If it's an absolute URI, nothing to suggest if (Uri.TryCreate(path, UriKind.Absolute, out Uri _)) { return; } IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); string thisDirMethod = s.RequestInfo.GetDirectoryMethodListing(); List <TreeNode> roots = new List <TreeNode>(); Formatter formatter = new Formatter(); roots.Add(new TreeNode(formatter, ".", thisDirMethod)); if (s.Parent != null) { string parentDirMethod = s.Parent.RequestInfo.GetDirectoryMethodListing(); roots.Add(new TreeNode(formatter, "..", parentDirMethod)); } int recursionDepth = 1; if (commandInput.Options[RecursiveOption].Count > 0) { if (string.IsNullOrEmpty(commandInput.Options[RecursiveOption][0]?.Text)) { recursionDepth = int.MaxValue; } else if (int.TryParse(commandInput.Options[RecursiveOption][0].Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rd) && rd > 1) { recursionDepth = rd; } } foreach (string child in s.DirectoryNames) { IDirectoryStructure dir = s.GetChildDirectory(child); string methods = dir.RequestInfo.GetDirectoryMethodListing(); TreeNode dirNode = new TreeNode(formatter, child, methods); roots.Add(dirNode); Recurse(dirNode, dir, recursionDepth - 1); } foreach (TreeNode node in roots) { shellState.ConsoleManager.WriteLine(node.ToString()); } bool hasVerboseOption = commandInput.Options[VerboseOption].Count > 0; bool hasRequestMethods = s.RequestInfo?.Methods?.Count > 0; if (hasVerboseOption && hasRequestMethods) { shellState.ConsoleManager.WriteLine(); shellState.ConsoleManager.WriteLine(Resources.Strings.ListCommand_AvailableMethods); foreach (string method in s.RequestInfo.Methods) { shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); IReadOnlyList <string> accepts = s.RequestInfo.ContentTypesByMethod[method]; string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); if (!string.IsNullOrEmpty(acceptsString)) { shellState.ConsoleManager.WriteLine($" {Resources.Strings.ListCommand_Accepts} " + acceptsString); } } } }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { var helpText = new StringBuilder(); helpText.Append("Usage: ".Bold()); helpText.AppendLine($"{Verb.ToUpperInvariant()} [Options]"); helpText.AppendLine(); helpText.AppendLine($"Issues a {Verb.ToUpperInvariant()} request."); if (RequiresBody) { helpText.AppendLine("Your default editor will be opened with a sample body if no options are provided."); } return(helpText.ToString()); }
protected override IEnumerable <string> GetOptionValueCompletions(IShellState shellState, HttpState programState, string optionId, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, string normalizedCompletionText) { if (string.Equals(optionId, BodyFileOption, StringComparison.Ordinal) || string.Equals(optionId, ResponseFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseBodyFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseHeadersFileOption, StringComparison.OrdinalIgnoreCase)) { return(FileSystemCompletion.GetCompletions(normalizedCompletionText)); } if (string.Equals(optionId, HeaderOption, StringComparison.Ordinal)) { HashSet <string> alreadySpecifiedHeaders = new HashSet <string>(StringComparer.Ordinal); IReadOnlyList <InputElement> options = commandInput.Options[HeaderOption]; for (int i = 0; i < options.Count; ++i) { if (options[i] == commandInput.SelectedElement) { continue; } string elementText = options[i].Text; string existingHeaderName = elementText.Split(HeaderSeparatorChars)[0]; alreadySpecifiedHeaders.Add(existingHeaderName); } //Check to see if the selected element is in a header name or value int equalsIndex = normalizedCompletionText.IndexOfAny(HeaderSeparatorChars); string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty; if (equalsIndex < 0) { IEnumerable <string> headerNameOptions = HeaderCompletion.GetCompletions(alreadySpecifiedHeaders, normalizedCompletionText); List <string> allSuggestions = new List <string>(); foreach (string suggestion in headerNameOptions.Select(x => x)) { allSuggestions.Add(suggestion + ":"); IEnumerable <string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, suggestion, string.Empty, programState); if (suggestions != null) { foreach (string valueSuggestion in suggestions) { allSuggestions.Add(suggestion + ":" + valueSuggestion); } } } return(allSuggestions); } else { //Didn't exit from the header name check, so must be a value string headerName = normalizedCompletionText.Substring(0, equalsIndex); IEnumerable <string> suggestions = HeaderCompletion.GetValueCompletions(Verb, path, headerName, normalizedCompletionText.Substring(equalsIndex + 1), programState); if (suggestions == null) { return(null); } return(suggestions.Select(x => normalizedCompletionText.Substring(0, equalsIndex + 1) + x)); } } return(null); }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { var helpText = new StringBuilder(); helpText.Append(Resources.Strings.Usage.Bold()); helpText.AppendLine($"echo [on|off]"); helpText.AppendLine(); helpText.AppendLine($"Turns request echoing on or off. When request echoing is on we will display a text representation of requests made by the CLI."); return(helpText.ToString()); }
private void HandleRequiresBody(DefaultCommandInput <ICoreParseResult> commandInput, IShellState shellState, HttpState programState, HttpRequestMessage request, Dictionary <string, string> requestHeaders) { string filePath = null; string bodyContent = null; bool deleteFile = false; bool noBody = commandInput.Options[NoBodyOption].Count > 0; if (!requestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable <string> contentTypes)) { contentType = contentTypes.FirstOrDefault(); } if (!noBody) { if (string.IsNullOrEmpty(contentType)) { contentType = "application/json"; } if (commandInput.Options[BodyFileOption].Count > 0) { filePath = commandInput.Options[BodyFileOption][0].Text; if (!_fileSystem.FileExists(filePath)) { shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".SetColor(programState.ErrorColor)); return; } } else if (commandInput.Options[BodyContentOption].Count > 0) { bodyContent = commandInput.Options[BodyContentOption][0].Text; } else { string defaultEditorCommand = _preferences.GetValue(WellKnownPreference.DefaultEditorCommand, null); if (defaultEditorCommand == null) { shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".SetColor(programState.ErrorColor)); return; } deleteFile = true; filePath = _fileSystem.GetTempFileName(); string exampleBody = GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, ref contentType, Verb, programState); if (!string.IsNullOrEmpty(exampleBody)) { _fileSystem.WriteAllTextToFile(filePath, exampleBody); } string defaultEditorArguments = _preferences.GetValue(WellKnownPreference.DefaultEditorArguments, null) ?? ""; string original = defaultEditorArguments; string pathString = $"\"{filePath}\""; defaultEditorArguments = defaultEditorArguments.Replace("{filename}", pathString); if (string.Equals(defaultEditorArguments, original, StringComparison.Ordinal)) { defaultEditorArguments = (defaultEditorArguments + " " + pathString).Trim(); } ProcessStartInfo info = new ProcessStartInfo(defaultEditorCommand, defaultEditorArguments); Process.Start(info)?.WaitForExit(); } } if (string.IsNullOrEmpty(contentType)) { contentType = "application/json"; } byte[] data = noBody ? new byte[0] : string.IsNullOrEmpty(bodyContent) ? _fileSystem.ReadAllBytesFromFile(filePath) : Encoding.UTF8.GetBytes(bodyContent); HttpContent content = new ByteArrayContent(data); content.Headers.ContentType = new MediaTypeHeaderValue(contentType); request.Content = content; if (deleteFile) { _fileSystem.DeleteFile(filePath); } AddHttpContentHeaders(content, programState, requestHeaders); }
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) { return(GetSetting(shellState, programState, commandInput)); } return(SetSetting(shellState, programState, commandInput)); }
protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput) { commandInput = commandInput ?? throw new ArgumentNullException(nameof(commandInput)); shellState = shellState ?? throw new ArgumentNullException(nameof(shellState)); programState = programState ?? throw new ArgumentNullException(nameof(programState)); if (commandInput.Arguments.Count == 0 || !_allowedModes.Contains(commandInput.Arguments[0]?.Text)) { shellState.ConsoleManager.Error.WriteLine(Resources.Strings.EchoCommand_Error_AllowedModes.SetColor(programState.ErrorColor)); return(false); } return(true); }
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _))) { shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".SetColor(programState.ErrorColor)); return; } if (programState.SwaggerEndpoint != null) { string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto"); if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase)) { await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false); } } Dictionary <string, string> thisRequestHeaders = new Dictionary <string, string>(); foreach (InputElement header in commandInput.Options[HeaderOption]) { int equalsIndex = header.Text.IndexOfAny(HeaderSeparatorChars); if (equalsIndex < 0) { shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".SetColor(programState.ErrorColor)); return; } thisRequestHeaders[header.Text.Substring(0, equalsIndex)] = header.Text.Substring(equalsIndex + 1); } Uri effectivePath = programState.GetEffectivePath(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty); HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Verb.ToUpperInvariant()), effectivePath); bool noBody = false; if (RequiresBody) { string filePath = null; string bodyContent = null; bool deleteFile = false; noBody = commandInput.Options[NoBodyOption].Count > 0; if (!noBody) { if (commandInput.Options[BodyFileOption].Count > 0) { filePath = commandInput.Options[BodyFileOption][0].Text; if (!File.Exists(filePath)) { shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".SetColor(programState.ErrorColor)); return; } } else if (commandInput.Options[BodyContentOption].Count > 0) { bodyContent = commandInput.Options[BodyContentOption][0].Text; } else { string defaultEditorCommand = programState.GetStringPreference(WellKnownPreference.DefaultEditorCommand); if (defaultEditorCommand == null) { shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".SetColor(programState.ErrorColor)); return; } deleteFile = true; filePath = Path.GetTempFileName(); if (!thisRequestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable <string> contentTypes)) { contentType = contentTypes.FirstOrDefault(); } if (contentType == null) { contentType = "application/json"; } string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, contentType, Verb); request.Headers.TryAddWithoutValidation("Content-Type", contentType); if (!string.IsNullOrEmpty(exampleBody)) { File.WriteAllText(filePath, exampleBody); } string defaultEditorArguments = programState.GetStringPreference(WellKnownPreference.DefaultEditorArguments) ?? ""; string original = defaultEditorArguments; string pathString = $"\"{filePath}\""; defaultEditorArguments = defaultEditorArguments.Replace("{filename}", pathString); if (string.Equals(defaultEditorArguments, original, StringComparison.Ordinal)) { defaultEditorArguments = (defaultEditorArguments + " " + pathString).Trim(); } ProcessStartInfo info = new ProcessStartInfo(defaultEditorCommand, defaultEditorArguments); Process.Start(info)?.WaitForExit(); } } byte[] data = noBody ? new byte[0] : string.IsNullOrEmpty(bodyContent) ? File.ReadAllBytes(filePath) : Encoding.UTF8.GetBytes(bodyContent); HttpContent content = new ByteArrayContent(data); request.Content = content; if (deleteFile) { File.Delete(filePath); } foreach (KeyValuePair <string, IEnumerable <string> > header in programState.Headers) { content.Headers.TryAddWithoutValidation(header.Key, header.Value); } foreach (KeyValuePair <string, string> header in thisRequestHeaders) { content.Headers.TryAddWithoutValidation(header.Key, header.Value); } } foreach (KeyValuePair <string, IEnumerable <string> > header in programState.Headers) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } foreach (KeyValuePair <string, string> header in thisRequestHeaders) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } string headersTarget = commandInput.Options[ResponseHeadersFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); }
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { if (programState.BaseAddress == null) { shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to query configuration".SetColor(programState.ErrorColor)); return; } if (string.IsNullOrEmpty(programState.DiagnosticsState.DiagnosticsEndpoint)) { shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint must be set to query configuration (see set diag)".SetColor(programState.ErrorColor)); return; } string configUrl = programState.DiagnosticsState.DiagnosticItems.FirstOrDefault(x => x.DisplayName == "Configuration")?.Url; if (configUrl == null) { shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint does not expose configuration information".SetColor(programState.ErrorColor)); return; } HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, configUrl), cancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { shellState.ConsoleManager.Error.WriteLine("Unable to get configuration information from diagnostics endpoint".SetColor(programState.ErrorColor)); return; } List <ConfigItem> configItems = await response.Content.ReadAsAsync <List <ConfigItem> >(cancellationToken).ConfigureAwait(false); foreach (ConfigItem item in configItems) { shellState.ConsoleManager.WriteLine($"{item.Key.Cyan()}: {item.Value}"); } }
private static async Task HandleResponseAsync(HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) { RequestConfig requestConfig = new RequestConfig(programState); ResponseConfig responseConfig = new ResponseConfig(programState); string protocolInfo; if (echoRequest) { string hostString = response.RequestMessage.RequestUri.Scheme + "://" + response.RequestMessage.RequestUri.Host + (!response.RequestMessage.RequestUri.IsDefaultPort ? ":" + response.RequestMessage.RequestUri.Port : ""); consoleManager.WriteLine($"Request to {hostString}...".SetColor(requestConfig.AddressColor)); consoleManager.WriteLine(); string method = response.RequestMessage.Method.ToString().ToUpperInvariant().SetColor(requestConfig.MethodColor); string pathAndQuery = response.RequestMessage.RequestUri.PathAndQuery.SetColor(requestConfig.AddressColor); protocolInfo = $"{"HTTP".SetColor(requestConfig.ProtocolNameColor)}{"/".SetColor(requestConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}"; consoleManager.WriteLine($"{method} {pathAndQuery} {protocolInfo}"); IEnumerable <KeyValuePair <string, IEnumerable <string> > > requestHeaders = response.RequestMessage.Headers; if (response.RequestMessage.Content != null) { requestHeaders = requestHeaders.Union(response.RequestMessage.Content.Headers); } foreach (KeyValuePair <string, IEnumerable <string> > header in requestHeaders.OrderBy(x => x.Key)) { string headerKey = header.Key.SetColor(requestConfig.HeaderKeyColor); string headerSep = ":".SetColor(requestConfig.HeaderSeparatorColor); string headerValue = string.Join(";".SetColor(requestConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(requestConfig.HeaderValueColor))); consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}"); } consoleManager.WriteLine(); if (response.RequestMessage.Content != null) { using (StreamWriter writer = new StreamWriter(new MemoryStream())) { await FormatBodyAsync(commandInput, programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); } } consoleManager.WriteLine(); consoleManager.WriteLine($"Response from {hostString}...".SetColor(requestConfig.AddressColor)); consoleManager.WriteLine(); } protocolInfo = $"{"HTTP".SetColor(responseConfig.ProtocolNameColor)}{"/".SetColor(responseConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(responseConfig.ProtocolVersionColor)}"; string status = ((int)response.StatusCode).ToString().SetColor(responseConfig.StatusCodeColor) + " " + response.ReasonPhrase.SetColor(responseConfig.StatusReasonPhraseColor); consoleManager.WriteLine($"{protocolInfo} {status}"); IEnumerable <KeyValuePair <string, IEnumerable <string> > > responseHeaders = response.Headers; if (response.Content != null) { responseHeaders = responseHeaders.Union(response.Content.Headers); } StreamWriter headerFileWriter; if (headersTargetFile != null) { headerFileWriter = new StreamWriter(File.Create(headersTargetFile)); } else { headerFileWriter = new StreamWriter(new MemoryStream()); } foreach (KeyValuePair <string, IEnumerable <string> > header in responseHeaders.OrderBy(x => x.Key)) { string headerKey = header.Key.SetColor(responseConfig.HeaderKeyColor); string headerSep = ":".SetColor(responseConfig.HeaderSeparatorColor); string headerValue = string.Join(";".SetColor(responseConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(responseConfig.HeaderValueColor))); consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}"); headerFileWriter.WriteLine($"{header.Key}: {string.Join(";", header.Value.Select(x => x.Trim()))}"); } StreamWriter bodyFileWriter; if (!string.Equals(headersTargetFile, bodyTargetFile, StringComparison.Ordinal)) { headerFileWriter.Flush(); headerFileWriter.Close(); headerFileWriter.Dispose(); if (bodyTargetFile != null) { bodyFileWriter = new StreamWriter(File.Create(bodyTargetFile)); } else { bodyFileWriter = new StreamWriter(new MemoryStream()); } } else { headerFileWriter.WriteLine(); bodyFileWriter = headerFileWriter; } consoleManager.WriteLine(); if (response.Content != null) { await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); } bodyFileWriter.Flush(); bodyFileWriter.Close(); bodyFileWriter.Dispose(); consoleManager.WriteLine(); }
private static async Task FormatBodyAsync(DefaultCommandInput <ICoreParseResult> commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) { if (commandInput.Options[StreamingOption].Count > 0) { Memory <char> buffer = new Memory <char>(new char[2048]); Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); StreamReader reader = new StreamReader(s); consoleManager.WriteLine("Streaming the response, press any key to stop...".SetColor(programState.WarningColor)); while (!cancellationToken.IsCancellationRequested) { try { ValueTask <int> readTask = reader.ReadAsync(buffer, cancellationToken); if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false)) { if (readTask.Result == 0) { break; } string str = new string(buffer.Span.Slice(0, readTask.Result)); consoleManager.Write(str); bodyFileWriter.Write(str); } else { break; } } catch (OperationCanceledException) { } } return; } string contentType = null; if (content.Headers.TryGetValues("Content-Type", out IEnumerable <string> contentTypeValues)) { contentType = contentTypeValues.FirstOrDefault()?.Split(';').FirstOrDefault(); } contentType = contentType?.ToUpperInvariant() ?? "text/plain"; if (commandInput.Options[NoFormattingOption].Count == 0) { if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) { if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) { return; } } else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) { if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) { return; } } } string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false); bodyFileWriter.WriteLine(responseContent); consoleManager.WriteLine(responseContent); }
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { commandInput = commandInput ?? throw new ArgumentNullException(nameof(commandInput)); shellState = shellState ?? throw new ArgumentNullException(nameof(shellState)); programState = programState ?? throw new ArgumentNullException(nameof(programState)); string rootAddress = commandInput.Arguments.SingleOrDefault()?.Text?.EnsureTrailingSlash(); string baseAddress = GetBaseAddressFromCommand(commandInput)?.EnsureTrailingSlash(); string swaggerAddress = GetSwaggerAddressFromCommand(commandInput); ApiConnection connectionInfo = GetConnectionInfo(shellState, programState, rootAddress, baseAddress, swaggerAddress, _preferences); if (connectionInfo is null) { return; } await connectionInfo.SetupHttpState(programState, performAutoDetect : true, cancellationToken); WriteStatus(shellState, programState); }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { if (parseResult.ContainsAtLeast(Name)) { var helpText = new StringBuilder(); helpText.Append(Resources.Strings.Usage.Bold()); helpText.AppendLine("connect [rootAddress] [--base baseAddress] [--openapi openApiDescriptionAddress]"); helpText.AppendLine(); helpText.AppendLine(Resources.Strings.ConnectCommand_HelpDetails_Line1); helpText.AppendLine(); helpText.AppendLine(Resources.Strings.ConnectCommand_HelpDetails_Line2); helpText.AppendLine(Resources.Strings.ConnectCommand_HelpDetails_Line3); return(helpText.ToString()); } return(null); }
private static string GetSwaggerAddressFromCommand(DefaultCommandInput <ICoreParseResult> commandInput) { return(GetOptionValueFromCommand(commandInput, SwaggerAddressOption)); }
protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput) { if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text)) { shellState.ConsoleManager.Error.WriteLine("Whether get or set settings must be specified"); return(false); } if (!string.Equals("get", commandInput.Arguments[0].Text) && (commandInput.Arguments.Count < 2 || string.IsNullOrEmpty(commandInput.Arguments[1]?.Text))) { shellState.ConsoleManager.Error.WriteLine("The preference to set must be specified"); return(false); } return(true); }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { return("config - Gets configuration information for the site if connected to a diagnostics endpoint"); }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text)) { return("pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value"); } if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) { return("pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified"); } else { return("pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference"); } }
protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { shellState.IsExiting = true; return(Task.CompletedTask); }
private static Task SetSetting(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput) { string prefName = commandInput.Arguments[1].Text; string prefValue = commandInput.Arguments.Count > 2 ? commandInput.Arguments[2]?.Text : null; if (string.IsNullOrEmpty(prefValue)) { if (!programState.DefaultPreferences.TryGetValue(prefName, out string defaultValue)) { programState.Preferences.Remove(prefName); } else { programState.Preferences[prefName] = defaultValue; } } else { programState.Preferences[prefName] = prefValue; } if (!programState.SavePreferences()) { shellState.ConsoleManager.Error.WriteLine("Error saving preferences".SetColor(programState.ErrorColor)); } return(Task.CompletedTask); }
protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { return("Exits the shell"); }
protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { shellState = shellState ?? throw new ArgumentNullException(nameof(shellState)); commandInput = commandInput ?? throw new ArgumentNullException(nameof(commandInput)); programState = programState ?? throw new ArgumentNullException(nameof(programState)); bool turnOn = string.Equals(commandInput.Arguments[0].Text, "on", StringComparison.OrdinalIgnoreCase); programState.EchoRequest = turnOn; shellState.ConsoleManager.WriteLine("Request echoing is " + (turnOn ? "on" : "off")); return(Task.CompletedTask); }
protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { shellState = shellState ?? throw new ArgumentNullException(nameof(shellState)); shellState.IsExiting = true; return(Task.CompletedTask); }
protected override IEnumerable <string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput <ICoreParseResult> commandInput, string normalCompletionString) { List <string> result = _allowedModes.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)).ToList(); return(result.Count > 0 ? result : null); }
protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { var helpText = new StringBuilder(); helpText.Append(Resources.Strings.Usage.Bold()); helpText.AppendLine($"exit"); helpText.AppendLine(); helpText.AppendLine($"Exits the shell"); return(helpText.ToString()); }
private async Task HandleResponseAsync(HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) { string protocolInfo; if (echoRequest) { await HandleEchoRequest(commandInput, consoleManager, programState, response, cancellationToken); } ResponseConfig responseConfig = new ResponseConfig(_preferences); protocolInfo = $"{"HTTP".SetColor(responseConfig.ProtocolNameColor)}{"/".SetColor(responseConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(responseConfig.ProtocolVersionColor)}"; string status = ((int)response.StatusCode).ToString().SetColor(responseConfig.StatusCodeColor) + " " + response.ReasonPhrase.SetColor(responseConfig.StatusReasonPhraseColor); consoleManager.WriteLine($"{protocolInfo} {status}"); IEnumerable <KeyValuePair <string, IEnumerable <string> > > responseHeaders = response.Headers; if (response.Content != null) { responseHeaders = responseHeaders.Union(response.Content.Headers); } List <string> headerFileOutput = null; List <string> bodyFileOutput = null; if (headersTargetFile != null) { headerFileOutput = new List <string>(); } foreach (KeyValuePair <string, IEnumerable <string> > header in responseHeaders.OrderBy(x => x.Key)) { string headerKey = header.Key.SetColor(responseConfig.HeaderKeyColor); string headerSep = ":".SetColor(responseConfig.HeaderSeparatorColor); string headerValue = string.Join(";".SetColor(responseConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(responseConfig.HeaderValueColor))); consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}"); headerFileOutput?.Add($"{header.Key}: {string.Join(";", header.Value.Select(x => x.Trim()))}"); } if (bodyTargetFile != null) { bodyFileOutput = new List <string>(); } consoleManager.WriteLine(); if (response.Content != null) { await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileOutput, _preferences, cancellationToken).ConfigureAwait(false); } if (headersTargetFile != null && !string.Equals(headersTargetFile, bodyTargetFile, StringComparison.Ordinal)) { headerFileOutput.Add(""); IEnumerable <string> allOutput = headerFileOutput.Concat(bodyFileOutput); _fileSystem.WriteAllLinesToFile(headersTargetFile, allOutput); } else { if (headersTargetFile != null && headerFileOutput != null) { _fileSystem.WriteAllLinesToFile(headersTargetFile, headerFileOutput); } if (bodyTargetFile != null && bodyFileOutput != null) { _fileSystem.WriteAllLinesToFile(bodyTargetFile, bodyFileOutput); } } consoleManager.WriteLine(); }
private static Task GetSetting(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput) { string preferenceName = commandInput.Arguments.Count > 1 ? commandInput.Arguments[1]?.Text : null; //If there's a particular setting to get the value of if (!string.IsNullOrEmpty(preferenceName)) { if (programState.Preferences.TryGetValue(preferenceName, out string value)) { shellState.ConsoleManager.WriteLine("Configured value: " + value); } else { shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + " does not have a configured value").SetColor(programState.ErrorColor)); } } else { foreach (KeyValuePair <string, string> entry in programState.Preferences.OrderBy(x => x.Key)) { shellState.ConsoleManager.WriteLine($"{entry.Key}={entry.Value}"); } } return(Task.CompletedTask); }
protected override IEnumerable <string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput <ICoreParseResult> commandInput, string normalCompletionString) { List <string> results = new List <string>(); if (programState.Structure != null && programState.BaseAddress != null) { //If it's an absolute URI, nothing to suggest if (Uri.TryCreate(parseResult.Sections[1], UriKind.Absolute, out Uri _)) { return(null); } string path = normalCompletionString.Replace('\\', '/'); int searchFrom = normalCompletionString.Length - 1; int lastSlash = path.LastIndexOf('/', searchFrom); string prefix; if (lastSlash < 0) { path = string.Empty; prefix = normalCompletionString; } else { path = path.Substring(0, lastSlash + 1); prefix = normalCompletionString.Substring(lastSlash + 1); } IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); foreach (string child in s.DirectoryNames) { if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { results.Add(path + child); } } } return(results); }
protected override IEnumerable <string> GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput <ICoreParseResult> commandInput, string normalCompletionString) { if (parseResult.SelectedSection == 1) { return(_allowedSubcommands.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase))); } if (parseResult.SelectedSection == 2) { string prefix = parseResult.Sections.Count > 2 ? normalCompletionString : string.Empty; List <string> matchingProperties = new List <string>(); foreach (string val in WellKnownPreference.Catalog.Names) { if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { matchingProperties.Add(val); } } return(matchingProperties); } if (parseResult.SelectedSection == 3 && parseResult.Sections[2].StartsWith("colors.", StringComparison.OrdinalIgnoreCase)) { string prefix = parseResult.Sections.Count > 3 ? normalCompletionString : string.Empty; List <string> matchingProperties = new List <string>(); foreach (string val in Enum.GetNames(typeof(AllowedColors))) { if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { matchingProperties.Add(val); } } return(matchingProperties); } return(null); }
protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out _))) { shellState.ConsoleManager.Error.WriteLine(Resources.Strings.Error_NoBasePath.SetColor(programState.ErrorColor)); return; } if (programState.SwaggerEndpoint != null) { await CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, cancellationToken).ConfigureAwait(false); } Dictionary <string, string> thisRequestHeaders = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (InputElement header in commandInput.Options[HeaderOption]) { int equalsIndex = header.Text.IndexOfAny(HeaderSeparatorChars); if (equalsIndex < 0) { shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".SetColor(programState.ErrorColor)); return; } thisRequestHeaders[header.Text.Substring(0, equalsIndex)] = header.Text.Substring(equalsIndex + 1); } Uri effectivePath = programState.GetEffectivePath(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty); HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Verb.ToUpperInvariant()), effectivePath); if (RequiresBody) { HandleRequiresBody(commandInput, shellState, programState, request, thisRequestHeaders); } foreach (KeyValuePair <string, IEnumerable <string> > header in programState.Headers) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } foreach (KeyValuePair <string, string> header in thisRequestHeaders) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } string headersTarget = commandInput.Options[ResponseHeadersFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); }
protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult) { var helpText = new StringBuilder(); helpText.Append(Resources.Strings.Usage.Bold()); helpText.AppendLine($"ls [Options]"); helpText.AppendLine(); helpText.AppendLine($"Displays the known routes at the current location. Requires a Swagger document to be set."); return(helpText.ToString()); }