public static WebServerResult OnMarkdownMonsterOperationHandler(WebServerOperation operation) { var result = mmApp.Model.Window.Dispatcher.Invoke(() => { // Opens Markdown Monster using MM's command line options if (operation.Operation == "open" && !string.IsNullOrEmpty(operation.Data)) { // Open Markdown Monster documents //App.CommandArgs = new[] {operation.Data}; mmApp.Model.Window.Dispatcher.InvokeAsync(() => { var opener = new CommandLineOpener(mmApp.Model.Window); opener.OpenFilesFromCommandLine(new[] { operation.Data }); }); } // Opens the specified document from disk else if (operation.Operation == "openDocument") { var tab = mmApp.Model.Window.OpenFile(operation.Data); if (tab != null) { mmApp.Model.Window.ActivateTab(tab); } } else if (operation.Operation == "openNew") { var tab = mmApp.Model.Window.OpenTab("untitled"); if (tab != null) { mmApp.Model.Window.ActivateTab(tab); var editor = tab.Tag as MarkdownDocumentEditor; if (editor != null) { mmApp.Model.Window.Dispatcher.InvokeAsync(() => { editor.SetMarkdown(operation.Data); editor.PreviewMarkdownCallback(); // refresh the preview }, System.Windows.Threading.DispatcherPriority.ApplicationIdle); } } } // Get the active document else if (operation.Operation == "getDocument") { var md = mmApp.Model?.ActiveEditor?.GetMarkdown(); var r = new WebServerResult((object)md); return(r); } // return a no data result return(new WebServerResult()); }); return(result); }
/// <summary> /// Writes a response with a full WebServerResult structure /// that allows maximum control over the response output. /// </summary> /// <param name="result"></param> public void WriteResponse(WebServerResult result) { var status = "OK"; if (result.HttpStatusCode == 500) { status = "Server Error"; } else if (result.HttpStatusCode == 404) { status = "Not Found"; } else if (result.HttpStatusCode == 401) { status = "Unauthorized"; } else if (result.HttpStatusCode == 204) { status = "No Content"; } string headers = $"HTTP/1.1 {result.HttpStatusCode} {status}\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET,POST,PUT,OPTIONS\r\n" + "Access-Control-Allow-Headers: *\r\n"; if (result.hasNoData) { WriteResponseInternal(null, headers); } else { var json = JsonSerializationUtils.Serialize(result, formatJsonOutput: true); WriteResponseInternal(json, headers + "Content-Type: application/json\r\n"); } }
public void WriteErrorResponse(string message = null) { var result = new WebServerResult(message); WriteResponse(result); }
/// <summary> /// Writes a 204 response with no data /// </summary> public void WriteNoDataResponse() { var result = new WebServerResult(); WriteResponse(result); }
/// <summary> /// Creates a response with a data result /// </summary> /// <param name="data"></param> public void WriteDataResponse(object data) { var result = new WebServerResult(data); WriteResponse(result); }
public void RunServer() { TcpServer?.Stop(); try { TcpServer = new TcpListener(IPAddress.Parse(IpAddress), ServerPort); TcpServer.Start(); } catch (Exception ex) { var window = mmApp.Model?.Window; if (window != null) { window.Dispatcher.InvokeAsync(() => { mmApp.Model.Configuration.WebServer.IsRunning = false; window.ShowStatusError( $"Failed to start Web Server on `localhost:{ServerPort}`: {ex.Message}"); }); } return; } // enter to an infinite cycle to be able to handle every change in stream while (!Cancelled) { try { RequestContext = OpenConnection(); var capturedData = new List <byte>(); WaitForConnectionData(); if (!RequestContext.Connection.Connected) { continue; } if (RequestContext.Connection.Available == 0) { continue; } if (!ParseRequest()) { continue; } // Send CORS header so this can be accessed if (RequestContext.Verb == "OPTIONS") { WriteResponseInternal(null, "HTTP/1.1 200 OK\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET,POST,PUT,OPTIONS\r\n" + "Access-Control-Allow-Headers: *\r\n"); continue; // done here } else if (RequestContext.Verb == "POST" && (RequestContext.Path == "/markdownmonster" || RequestContext.Path.StartsWith("/markdownmonster/"))) { WebServerResult result = new WebServerResult(); try { var operation = JsonConvert.DeserializeObject(RequestContext.RequestContent, typeof(WebServerOperation)) as WebServerOperation; if (operation == null) { throw new ArgumentException("Invalid json request data: " + RequestContext.RequestContent); } try { result = OnMarkdownMonsterOperation?.Invoke(operation); } catch { mmApp.Model?.Window?.ShowStatusError("Web Server Client Request failed. Operation: " + operation.Operation); } } catch (Exception ex) { WriteErrorResponse("Markdown Monster Message Processing failed: " + ex.Message + "\r\n\r\n" + RequestContext.RequestContent); continue; } WriteResponse(result); } else if (RequestContext.Path.StartsWith("/ping")) { WriteDataResponse("OK"); } else { var result = new WebServerResult("Invalid URL access", 404); WriteResponse(result); } } catch (Exception ex) { WriteErrorResponse("An error occurred: " + ex.Message); } finally { // close connection CloseConnection(); RequestContext = null; } } }