| | | 1 | | using System.Management.Automation; |
| | | 2 | | using System.Text; |
| | | 3 | | using Serilog; |
| | | 4 | | |
| | | 5 | | namespace Kestrun.Utilities; |
| | | 6 | | |
| | | 7 | | /// <summary> |
| | | 8 | | /// Utilities for formatting PowerShell error streams into HTTP responses. |
| | | 9 | | /// </summary> |
| | | 10 | | public static class BuildError |
| | | 11 | | { |
| | | 12 | | /// <summary> |
| | | 13 | | /// Convert the current PowerShell error streams to a plain-text <see cref="IResult"/>. |
| | | 14 | | /// </summary> |
| | 1 | 15 | | public static IResult Result(PowerShell ps) => Results.Text(content: Text(ps), statusCode: 500, contentType: "text/p |
| | | 16 | | |
| | | 17 | | |
| | | 18 | | |
| | | 19 | | /// <summary> |
| | | 20 | | /// Collate all PowerShell streams (error, verbose, warning, etc.) into a single string. |
| | | 21 | | /// </summary> |
| | | 22 | | public static string Text(PowerShell ps) |
| | | 23 | | { |
| | 6 | 24 | | ArgumentNullException.ThrowIfNull(ps); |
| | | 25 | | |
| | 12 | 26 | | var errors = ps.Streams.Error.Select(e => e.ToString()); |
| | 6 | 27 | | var verbose = ps.Streams.Verbose.Select(v => v.ToString()); |
| | 6 | 28 | | var warnings = ps.Streams.Warning.Select(w => w.ToString()); |
| | 6 | 29 | | var debug = ps.Streams.Debug.Select(d => d.ToString()); |
| | 7 | 30 | | var info = ps.Streams.Information.Select(i => i.ToString()); |
| | | 31 | | // Format the output |
| | | 32 | | // 500 + text body |
| | | 33 | | |
| | 6 | 34 | | var sb = new StringBuilder(); |
| | | 35 | | |
| | | 36 | | void append(string emoji, IEnumerable<string> lines) |
| | | 37 | | { |
| | 30 | 38 | | if (!lines.Any()) |
| | | 39 | | { |
| | 23 | 40 | | return; |
| | | 41 | | } |
| | | 42 | | |
| | 7 | 43 | | _ = sb.AppendLine($"{emoji}[{emoji switch |
| | 7 | 44 | | { |
| | 6 | 45 | | "❌" => "Error", |
| | 0 | 46 | | "💬" => "Verbose", |
| | 0 | 47 | | "⚠️" => "Warning", |
| | 0 | 48 | | "🐞" => "Debug", |
| | 1 | 49 | | _ => "Info" |
| | 7 | 50 | | }}]"); |
| | 28 | 51 | | foreach (var l in lines) |
| | | 52 | | { |
| | 7 | 53 | | _ = sb.AppendLine($"\t{l}"); |
| | | 54 | | } |
| | 7 | 55 | | } |
| | | 56 | | |
| | 6 | 57 | | append("❌", errors); |
| | 6 | 58 | | append("💬", verbose); |
| | 6 | 59 | | append("⚠️", warnings); |
| | 6 | 60 | | append("🐞", debug); |
| | 6 | 61 | | append("ℹ️", info); |
| | | 62 | | |
| | 6 | 63 | | var msg = sb.ToString(); |
| | 6 | 64 | | Log.Information(msg); |
| | | 65 | | |
| | | 66 | | |
| | 6 | 67 | | return msg; |
| | | 68 | | } |
| | | 69 | | |
| | | 70 | | // Helper that writes the error to the response stream |
| | | 71 | | /// <summary> |
| | | 72 | | /// Write the formatted PowerShell errors directly to the HTTP response. |
| | | 73 | | /// </summary> |
| | | 74 | | public static Task ResponseAsync(HttpContext context, PowerShell ps) |
| | | 75 | | { |
| | 3 | 76 | | var errText = Text(ps); |
| | 3 | 77 | | context.Response.StatusCode = 500; |
| | 3 | 78 | | context.Response.ContentType = "text/plain; charset=utf-8"; |
| | 3 | 79 | | return context.Response.WriteAsync(errText); |
| | | 80 | | } |
| | | 81 | | } |