From 6b3f50e2b24c2d333108e29833bd15c61120d640 Mon Sep 17 00:00:00 2001 From: Cristian Pufu Date: Sun, 25 Aug 2024 21:05:28 +0300 Subject: [PATCH] Add webhook testing tool references --- .../HttpTunnel/HttpAppExtensions.cs | 153 ++++++++++-------- src/Tunnelite.Server/wwwroot/index.html | 65 ++++++-- 2 files changed, 133 insertions(+), 85 deletions(-) diff --git a/src/Tunnelite.Server/HttpTunnel/HttpAppExtensions.cs b/src/Tunnelite.Server/HttpTunnel/HttpAppExtensions.cs index 9964988..0803681 100644 --- a/src/Tunnelite.Server/HttpTunnel/HttpAppExtensions.cs +++ b/src/Tunnelite.Server/HttpTunnel/HttpAppExtensions.cs @@ -33,7 +33,8 @@ public static void UseHttpTunneling(this WebApplication app) { // reserved if (payload.Subdomain.Equals("localhost", StringComparison.OrdinalIgnoreCase) || - payload.Subdomain.Equals("tunnelite", StringComparison.OrdinalIgnoreCase)) + payload.Subdomain.Equals("tunnelite", StringComparison.OrdinalIgnoreCase) || + payload.Subdomain.Equals("webhooks", StringComparison.OrdinalIgnoreCase)) { payload.Subdomain = RandomSubdomain(); } @@ -253,79 +254,93 @@ await context.Response.WriteAsJsonAsync(new static async Task TunnelRequestAsync(WebApplication app, HttpContext context, IHubContext hubContext, HttpRequestsQueue requestsQueue, HttpTunnelStore tunnelStore, string path, ILogger logger) { - try - { - HttpTunnelRequest? tunnel = null; - - var subdomain = context.Request.Host.Host.Split('.')[0]; - - if (subdomain.Equals("localhost", StringComparison.OrdinalIgnoreCase)) - { - tunnel = tunnelStore.Tunnels.FirstOrDefault().Value; - } - else if (subdomain.Equals("tunnelite")) - { - var filePath = Path.Combine(app.Environment.WebRootPath, "index.html"); - - if (File.Exists(filePath)) - { - context.Response.ContentType = "text/html"; - await context.Response.SendFileAsync(filePath); - } - else - { - context.Response.StatusCode = StatusCodes.Status404NotFound; - await context.Response.WriteAsync("Index page not found"); - } - return; - } - else - { - tunnelStore.Tunnels.TryGetValue(subdomain, out tunnel); - } + var filePath = Path.Combine(app.Environment.WebRootPath, "index.html"); - if (tunnel == null) - { - context.Response.StatusCode = StatusCodes.Status404NotFound; - await context.Response.WriteAsync(NotFound); - return; - } - - if (!tunnelStore.Connections.TryGetValue(tunnel!.ClientId, out var connectionId)) - { - context.Response.StatusCode = StatusCodes.Status404NotFound; - await context.Response.WriteAsync(NotFound); - return; - } - - var requestId = Guid.NewGuid(); - - var completionTask = requestsQueue.WaitForCompletionAsync(requestId, context, timeout: TimeSpan.FromSeconds(30), context.RequestAborted); - - await hubContext.Clients.Client(connectionId).SendAsync("NewHttpConnection", new HttpConnection - { - RequestId = requestId, - ContentType = context.Request.ContentType, - Method = context.Request.Method, - Path = $"{tunnel.LocalUrl}/{path}{context.Request.QueryString}", - }); - - await completionTask; - } - catch (TaskCanceledException) + if (File.Exists(filePath)) { - // ignore + context.Response.ContentType = "text/html"; + await context.Response.SendFileAsync(filePath); } - catch (Exception ex) + else { - if (!context.Response.HasStarted) - { - context.Response.StatusCode = StatusCodes.Status500InternalServerError; - await context.Response.WriteAsync("An error occurred while processing the tunnel."); - } - - logger.LogError(ex, "Error processing request tunnel: {Message}", ex.Message); + context.Response.StatusCode = StatusCodes.Status404NotFound; + await context.Response.WriteAsync("Index page not found"); } + return; + + //try + //{ + // HttpTunnelRequest? tunnel = null; + + // var subdomain = context.Request.Host.Host.Split('.')[0]; + + // if (subdomain.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + // { + // tunnel = tunnelStore.Tunnels.FirstOrDefault().Value; + // } + // else if (subdomain.Equals("tunnelite")) + // { + // var filePath = Path.Combine(app.Environment.WebRootPath, "index.html"); + + // if (File.Exists(filePath)) + // { + // context.Response.ContentType = "text/html"; + // await context.Response.SendFileAsync(filePath); + // } + // else + // { + // context.Response.StatusCode = StatusCodes.Status404NotFound; + // await context.Response.WriteAsync("Index page not found"); + // } + // return; + // } + // else + // { + // tunnelStore.Tunnels.TryGetValue(subdomain, out tunnel); + // } + + // if (tunnel == null) + // { + // context.Response.StatusCode = StatusCodes.Status404NotFound; + // await context.Response.WriteAsync(NotFound); + // return; + // } + + // if (!tunnelStore.Connections.TryGetValue(tunnel!.ClientId, out var connectionId)) + // { + // context.Response.StatusCode = StatusCodes.Status404NotFound; + // await context.Response.WriteAsync(NotFound); + // return; + // } + + // var requestId = Guid.NewGuid(); + + // var completionTask = requestsQueue.WaitForCompletionAsync(requestId, context, timeout: TimeSpan.FromSeconds(30), context.RequestAborted); + + // await hubContext.Clients.Client(connectionId).SendAsync("NewHttpConnection", new HttpConnection + // { + // RequestId = requestId, + // ContentType = context.Request.ContentType, + // Method = context.Request.Method, + // Path = $"{tunnel.LocalUrl}/{path}{context.Request.QueryString}", + // }); + + // await completionTask; + //} + //catch (TaskCanceledException) + //{ + // // ignore + //} + //catch (Exception ex) + //{ + // if (!context.Response.HasStarted) + // { + // context.Response.StatusCode = StatusCodes.Status500InternalServerError; + // await context.Response.WriteAsync("An error occurred while processing the tunnel."); + // } + + // logger.LogError(ex, "Error processing request tunnel: {Message}", ex.Message); + //} } static string RandomSubdomain(int length = 8) diff --git a/src/Tunnelite.Server/wwwroot/index.html b/src/Tunnelite.Server/wwwroot/index.html index 07a5043..0566062 100644 --- a/src/Tunnelite.Server/wwwroot/index.html +++ b/src/Tunnelite.Server/wwwroot/index.html @@ -22,30 +22,57 @@ margin: 0; padding: 0; } + header { + background-color: #f8f9fa; + padding: 1rem 0; + } .container { max-width: 1200px; margin: 0 auto; - padding: 0 20px; - } - header { - background-color: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - padding: 20px 0; + padding: 0 1rem; } + nav { display: flex; justify-content: space-between; align-items: center; } + .logo { - font-size: 24px; + font-size: 1.5rem; font-weight: bold; - color: var(--primary-color); } - .nav-links a { - margin-left: 20px; - text-decoration: none; - color: var(--text-color); + + .nav-links { + display: flex; + align-items: center; + gap: 1rem; + } + + .nav-links a { + text-decoration: none; + color: #333; + font-size: 1rem; + transition: color 0.3s ease; + } + + .nav-links a:hover { + color: #007bff; + } + + .github-logo { + display: inline-block; + vertical-align: middle; + width: 24px; + height: 24px; + fill: currentColor; + } + + .nav-links a[aria-label="GitHub repository"] { + display: flex; + align-items: center; + height: 100%; + padding: 0; } .hero { text-align: center; @@ -151,13 +178,18 @@
@@ -177,8 +209,9 @@

Expose Local Apps

Share your locally-hosted web applications for testing or demos.

-

Test Webhooks

-

Easily test and debug webhook integrations by exposing your local endpoints to the internet.

+

Test and Debug Webhooks

+

Easily test webhook integrations by exposing local endpoints.

+ Try our webhook testing tool to inspect and debug incoming requests.

Hackathon Ready