示例#1
0
        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);
                    }
                }
            }
        }
示例#2
0
        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());
        }
示例#3
0
        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);
        }
示例#4
0
        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());
        }
示例#5
0
        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);
        }
示例#6
0
        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));
        }
示例#7
0
        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);
        }
示例#9
0
        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}");
            }
        }
示例#10
0
        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();
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
 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);
 }
示例#14
0
 private static string GetSwaggerAddressFromCommand(DefaultCommandInput <ICoreParseResult> commandInput)
 {
     return(GetOptionValueFromCommand(commandInput, SwaggerAddressOption));
 }
示例#15
0
        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);
        }
示例#16
0
 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");
 }
示例#17
0
        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");
            }
        }
示例#18
0
 protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken)
 {
     shellState.IsExiting = true;
     return(Task.CompletedTask);
 }
示例#19
0
        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);
        }
示例#20
0
 protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput <ICoreParseResult> commandInput, ICoreParseResult parseResult)
 {
     return("Exits the shell");
 }
示例#21
0
        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);
        }
示例#22
0
        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);
        }
示例#23
0
        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);
        }
示例#24
0
        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());
        }
示例#25
0
        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();
        }
示例#26
0
        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);
        }
示例#27
0
        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);
        }
示例#28
0
        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);
        }
示例#29
0
        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);
        }
示例#30
0
        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());
        }