Skip to content

Instantly share code, notes, and snippets.

@aktolu
Created April 26, 2026 03:14
Show Gist options
  • Select an option

  • Save aktolu/76e7ac93758e71f3c3ecdb16316226d0 to your computer and use it in GitHub Desktop.

Select an option

Save aktolu/76e7ac93758e71f3c3ecdb16316226d0 to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
Exposes a specific local XAMPP project directory to the internet via Cloudflare Tunnel using a full URL.
#>
# Prompt the user for the full local URL
$InputUrl = Read-Host "Please enter the full local URL (e.g., http://localhost/dev/proje/)"
# Clean the input and ensure it has a proper HTTP scheme
$InputUrl = $InputUrl.Trim()
if (-not $InputUrl.StartsWith("http://") -and -not $InputUrl.StartsWith("https://")) {
$InputUrl = "http://" + $InputUrl
}
# Extract the path from the inputted URL
$ParsedUri = [System.Uri]$InputUrl
$UrlPath = $ParsedUri.AbsolutePath
$LocalUrl = $InputUrl
Write-Host "Targeting local URL: $LocalUrl" -ForegroundColor Cyan
# Prepare a temporary file to capture the cloudflared standard error output
$TempLogFile = New-TemporaryFile
# Define arguments for the cloudflared process
# Pointing directly to the full URL perfectly isolates the tunnel,
# preventing any access to parent directories or other projects.
$Arguments = @(
"tunnel",
"--url", $LocalUrl,
"--no-tls-verify"
)
# Use NoNewWindow instead of Hidden WindowStyle.
# This attaches the child process to the current console.
# If the user closes the console window abruptly, Windows will automatically kill the attached cloudflared process.
$ProcessParams = @{
FilePath = "cloudflared"
ArgumentList = $Arguments
RedirectStandardError = $TempLogFile.FullName
NoNewWindow = $true
PassThru = $true
}
Write-Host "Starting Cloudflare tunnel..." -ForegroundColor Yellow
# Start the cloudflared background process
$TunnelProcess = Start-Process @ProcessParams
$TunnelUrl = $null
$TimeoutSeconds = 30
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
Write-Host "Waiting for the public URL to be generated..." -ForegroundColor Yellow
# Loop until the TryCloudflare URL is found in the log file or timeout is reached
while ($Stopwatch.Elapsed.TotalSeconds -lt $TimeoutSeconds -and -not $TunnelUrl) {
Start-Sleep -Milliseconds 500
# Read the file content silently to avoid file-in-use locking errors
$LogContent = Get-Content -Path $TempLogFile.FullName -Raw -ErrorAction SilentlyContinue
if ($LogContent -match "(https://[a-zA-Z0-9-]+\.trycloudflare\.com)") {
$TunnelUrl = $matches[1]
}
}
if ($TunnelUrl) {
# Construct the full URL by appending the extracted path
$TunnelUrl = $TunnelUrl.TrimEnd('/')
$FullUrl = "$TunnelUrl$UrlPath"
Write-Host "`n[SUCCESS] Tunnel established successfully!" -ForegroundColor Green
Write-Host "Public URL: $FullUrl" -ForegroundColor White
# Copy the URL to the clipboard
Set-Clipboard -Value $FullUrl
Write-Host "The URL has been copied to your clipboard." -ForegroundColor Green
# Wait for 5 seconds before opening the browser
Write-Host "Opening the browser in 5 seconds..." -ForegroundColor Cyan
Start-Sleep -Seconds 5
# Open the URL in the default web browser
Start-Process $FullUrl
} else {
Write-Host "`n[ERROR] Could not retrieve the tunnel URL within the timeout." -ForegroundColor Red
Write-Host "Make sure 'cloudflared' is installed and added to your system's PATH." -ForegroundColor Red
}
# Keep the script running to keep the proxy alive
try {
if (-not $TunnelProcess.HasExited) {
Write-Host "`nThe proxy is currently running. Close this window or press CTRL+C to stop it." -ForegroundColor Yellow
# Infinite loop to keep the PowerShell window open until the user manually closes it
while (-not $TunnelProcess.HasExited) {
Start-Sleep -Seconds 1
}
}
} finally {
# Clean up resources and kill the background process when the script exits gracefully via CTRL+C
if ($TunnelProcess -and -not $TunnelProcess.HasExited) {
Write-Host "`nStopping Cloudflare tunnel..." -ForegroundColor Yellow
$TunnelProcess.Kill()
}
if (Test-Path $TempLogFile.FullName) {
Remove-Item -Path $TempLogFile.FullName -Force -ErrorAction SilentlyContinue
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment