Update docs: new README, IIS guide, and production web.config
- Replaced README.md with a modern, production-focused version featuring quick start, architecture, workflow, troubleshooting, and security sections - Added DEPLOYMENT_GUIDE_IIS_Windows11.md with step-by-step IIS deployment instructions, including SSL, CORS, and permissions - Added version-controlled web.config files for API and Blazor app with HTTPS redirection, security headers, and SPA/static file support - Moved detailed yt-dlp integration notes to README_UPDATED.md for technical reference - Improves clarity, maintainability, and production readiness of documentation and deployment
This commit is contained in:
@@ -0,0 +1,723 @@
|
||||
# TuneRipper Deployment Guide - IIS on Windows 11
|
||||
|
||||
This guide provides step-by-step instructions for manually deploying the TuneRipper Blazor WebAssembly application and API to Internet Information Services (IIS) on Windows 11.
|
||||
|
||||
## Deployment Scenarios
|
||||
|
||||
### Scenario A: Production Server (Recommended)
|
||||
Deploy pre-built applications to a clean production server.
|
||||
**Requirements**: Only .NET 10 Hosting Bundle + IIS
|
||||
|
||||
### Scenario B: Build + Deploy on Same Machine
|
||||
Build and deploy applications on the same machine.
|
||||
**Requirements**: .NET 10 SDK + .NET 10 Hosting Bundle + IIS
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### System Requirements
|
||||
- Windows 11 (Pro, Enterprise, or Education edition recommended)
|
||||
- **IIS (Internet Information Services)** already installed and configured
|
||||
- Administrative privileges
|
||||
- Internet connection for downloading dependencies
|
||||
- **Domain names configured** (for production HTTPS setup)
|
||||
|
||||
### Software Dependencies
|
||||
- **.NET 10 Hosting Bundle** (production) OR **.NET 10 SDK** (development)
|
||||
- **yt-dlp.exe** (for video processing)
|
||||
- **ffmpeg** (required by yt-dlp for audio conversion)
|
||||
- **Let's Encrypt ACME tool** (for SSL certificates in production)
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Install .NET 10 Hosting Bundle for IIS
|
||||
|
||||
> **Critical**: This step is required for ALL deployment scenarios
|
||||
|
||||
### 1.1 Download .NET 10 Hosting Bundle
|
||||
The Hosting Bundle contains the ASP.NET Core runtime and IIS integration components needed to run .NET 10 applications on IIS.
|
||||
|
||||
1. Go to [Microsoft .NET Downloads](https://dotnet.microsoft.com/download/dotnet/10.0)
|
||||
2. Scroll to **"ASP.NET Core Runtime"** section
|
||||
3. Under **"Run server apps"**, find **"Hosting Bundle"**
|
||||
4. Download **"Hosting Bundle"** for Windows (e.g., `dotnet-hosting-10.0.x-win.exe`)
|
||||
5. **Important**: This is different from the SDK - it's specifically for IIS hosting
|
||||
|
||||
### 1.2 Install the Hosting Bundle
|
||||
1. Close all IIS Manager windows and web browsers
|
||||
2. Run the downloaded hosting bundle installer as **Administrator**
|
||||
3. Follow the installation wizard:
|
||||
- Accept license terms
|
||||
- Complete the installation
|
||||
4. **Critical**: Restart IIS services by running this command in **Command Prompt as Administrator**:
|
||||
```cmd
|
||||
iisreset /restart
|
||||
```
|
||||
5. Alternatively, restart the entire computer to ensure all services are updated
|
||||
|
||||
### 1.3 Verify Hosting Bundle Installation
|
||||
1. Open **Command Prompt as Administrator**
|
||||
2. Run: `dotnet --info`
|
||||
3. Look for the ASP.NET Core Module in IIS:
|
||||
```cmd
|
||||
%windir%\system32\inetsrv\appcmd.exe list modules
|
||||
```
|
||||
4. You should see `AspNetCoreModuleV2` in the output
|
||||
5. Check the registry for the module (PowerShell as Administrator):
|
||||
```powershell
|
||||
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\IIS Extensions\IIS AspNetCore Module V2"
|
||||
```
|
||||
|
||||
### 1.4 Verify ASP.NET Core Module Installation
|
||||
1. Open **IIS Manager** (`Win + R` ? `inetmgr`)
|
||||
2. Select your server name in the left panel
|
||||
3. Double-click **"Modules"** in the main panel
|
||||
4. Look for **"AspNetCoreModuleV2"** - it should be present and enabled
|
||||
5. If not visible, you may need to restart IIS again:
|
||||
```cmd
|
||||
iisreset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Install Required Tools
|
||||
|
||||
### 2.1 Download yt-dlp
|
||||
1. Go to [yt-dlp releases](https://github.com/yt-dlp/yt-dlp/releases)
|
||||
2. Download the latest `yt-dlp.exe` (Windows executable)
|
||||
3. **Important**: Keep this file ready for later deployment
|
||||
|
||||
### 2.2 Install FFmpeg
|
||||
1. Go to [FFmpeg downloads](https://ffmpeg.org/download.html#build-windows)
|
||||
2. Choose **"Windows"** ? **"Windows builds by BtbN"**
|
||||
3. Download the latest **"ffmpeg-master-latest-win64-gpl.zip"**
|
||||
4. Extract to `C:\ffmpeg\`
|
||||
5. Add `C:\ffmpeg\bin` to your System PATH:
|
||||
- Press `Win + X`, select **"System"**
|
||||
- Click **"Advanced system settings"**
|
||||
- Click **"Environment Variables"**
|
||||
- Under **"System Variables"**, find and edit **"Path"**
|
||||
- Click **"New"** and add: `C:\ffmpeg\bin`
|
||||
- Click **OK** to save all dialogs
|
||||
6. Restart Command Prompt and verify: `ffmpeg -version`
|
||||
|
||||
### 2.3 Install Let's Encrypt ACME Tool (Production HTTPS)
|
||||
For production deployment with custom domains, install an ACME client:
|
||||
|
||||
1. **Install win-acme (Recommended for Windows/IIS)**:
|
||||
- Go to [win-acme releases](https://github.com/win-acme/win-acme/releases)
|
||||
- Download the latest `win-acme.v2.x.x.x.pluggable.zip`
|
||||
- Extract to `C:\win-acme\`
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Get Application Files
|
||||
|
||||
### Option A: Use Pre-Built Files (Production Deployment)
|
||||
If you have pre-built application files from another machine:
|
||||
1. Copy the published API files to: `C:\Publish\TuneRipper.Api\`
|
||||
2. Copy the published Blazor WebAssembly files to: `C:\Publish\TuneRipper\`
|
||||
3. **Skip to Step 4** (Prepare Deployment Files)
|
||||
|
||||
### Option B: Build Applications (Build + Deploy Scenario)
|
||||
If you need to build the applications on this machine, continue below:
|
||||
|
||||
#### 3B.1 Install .NET 10 SDK (If Building Locally)
|
||||
1. Go to [Microsoft .NET Downloads](https://dotnet.microsoft.com/download/dotnet/10.0)
|
||||
2. Download and install the .NET 10 SDK
|
||||
3. Restart your computer after installation
|
||||
|
||||
#### 3B.2 Verify Build Environment
|
||||
Before publishing, ensure your development environment is ready:
|
||||
1. Open **Command Prompt** in your project directory: `C:\DevHome\TuneRipper`
|
||||
2. Run: `dotnet --version` (should show 10.0.x)
|
||||
3. Run: `dotnet restore` (restore NuGet packages)
|
||||
4. Run: `dotnet build` (verify everything compiles)
|
||||
|
||||
#### 3B.3 Publish the API (TuneRipper.Api)
|
||||
|
||||
**Using Visual Studio:**
|
||||
1. Open the TuneRipper solution in **Visual Studio 2022**
|
||||
2. Ensure you have **.NET 10 workload** installed in Visual Studio:
|
||||
- Go to **Tools** ? **Get Tools and Features**
|
||||
- Under **Workloads**, ensure **"ASP.NET and web development"** is checked
|
||||
- Under **Individual Components**, ensure **.NET 10 Runtime** is selected
|
||||
3. Right-click on **TuneRipper.Api** project
|
||||
4. Select **"Publish..."**
|
||||
5. Choose **"Folder"** as the publish target
|
||||
6. Set publish folder to: `C:\Publish\TuneRipper.Api`
|
||||
7. Click **"Show all settings"** and configure:
|
||||
- **Configuration**: `Release`
|
||||
- **Target Framework**: `net10.0`
|
||||
- **Deployment Mode**: `Framework-dependent`
|
||||
- **Target Runtime**: `Portable`
|
||||
8. Click **"Save"** and then **"Publish"**
|
||||
|
||||
**Using Command Line:**
|
||||
```cmd
|
||||
cd C:\DevHome\TuneRipper
|
||||
dotnet publish TuneRipper.Api\TuneRipper.Api.csproj -c Release -f net10.0 -o C:\Publish\TuneRipper.Api --verbosity normal
|
||||
```
|
||||
|
||||
#### 3B.4 Publish the Blazor WebAssembly App (TuneRipper)
|
||||
|
||||
**Using Visual Studio:**
|
||||
1. Right-click on **TuneRipper** project
|
||||
2. Select **"Publish..."**
|
||||
3. Choose **"Folder"** as the publish target
|
||||
4. Set publish folder to: `C:\Publish\TuneRipper`
|
||||
5. Configure settings:
|
||||
- **Configuration**: `Release`
|
||||
- **Target Framework**: `net10.0`
|
||||
6. Click **"Save"** and then **"Publish"**
|
||||
|
||||
**Using Command Line:**
|
||||
```cmd
|
||||
cd C:\DevHome\TuneRipper
|
||||
dotnet publish TuneRipper\TuneRipper.csproj -c Release -f net10.0 -o C:\Publish\TuneRipper --verbosity normal
|
||||
```
|
||||
|
||||
#### 3B.5 Verify Published Output
|
||||
After publishing, check the output directories:
|
||||
|
||||
**API Output** (`C:\Publish\TuneRipper.Api\`):
|
||||
- `TuneRipper.Api.dll`
|
||||
- `TuneRipper.Api.exe`
|
||||
- `web.config` (should be auto-generated)
|
||||
- `appsettings.json`
|
||||
- Various .NET 10 runtime files
|
||||
|
||||
**Blazor Output** (`C:\Publish\TuneRipper\`):
|
||||
- `wwwroot\` folder containing:
|
||||
- `index.html`
|
||||
- `_framework\` folder
|
||||
- Static assets (CSS, JS, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Prepare Deployment Files
|
||||
|
||||
### 4.1 Create Deployment Directories
|
||||
```cmd
|
||||
mkdir C:\inetpub\wwwroot\TuneRipper
|
||||
mkdir C:\inetpub\wwwroot\TuneRipperApi
|
||||
mkdir C:\inetpub\wwwroot\TuneRipperApi\wwwroot
|
||||
mkdir C:\inetpub\wwwroot\TuneRipperApi\wwwroot\downloads
|
||||
```
|
||||
|
||||
### 4.2 Copy API Files
|
||||
1. Copy all contents from `C:\Publish\TuneRipper.Api\` to `C:\inetpub\wwwroot\TuneRipperApi\`
|
||||
2. Copy `yt-dlp.exe` to `C:\inetpub\wwwroot\TuneRipperApi\wwwroot\yt-dlp.exe`
|
||||
3. Verify the API structure:
|
||||
```
|
||||
C:\inetpub\wwwroot\TuneRipperApi\
|
||||
??? TuneRipper.Api.dll
|
||||
??? TuneRipper.Api.exe
|
||||
??? appsettings.json
|
||||
??? web.config
|
||||
??? wwwroot\
|
||||
? ??? yt-dlp.exe
|
||||
? ??? downloads\
|
||||
??? [other .NET 10 runtime files]
|
||||
```
|
||||
|
||||
### 4.3 Copy Blazor WebAssembly Files
|
||||
1. Copy all contents from `C:\Publish\TuneRipper\wwwroot\` to `C:\inetpub\wwwroot\TuneRipper\`
|
||||
2. Verify the Blazor structure:
|
||||
```
|
||||
C:\inetpub\wwwroot\TuneRipper\
|
||||
??? index.html
|
||||
??? _framework\
|
||||
? ??? blazor.webassembly.js
|
||||
? ??? dotnet.10.x.x.js
|
||||
? ??? [.NET 10 WebAssembly files]
|
||||
??? css\
|
||||
??? images\
|
||||
??? [other static files]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Configure IIS Sites
|
||||
|
||||
### 5.1 Open IIS Manager
|
||||
1. Press `Win + R`, type `inetmgr`, press Enter
|
||||
2. IIS Manager should open
|
||||
|
||||
### 5.2 Create API Application
|
||||
1. In IIS Manager, expand the server node
|
||||
2. Right-click **"Sites"** ? **"Add Website..."**
|
||||
3. Configure the API site:
|
||||
- **Site name**: `TuneRipper API`
|
||||
- **Physical path**: `C:\inetpub\wwwroot\TuneRipperApi`
|
||||
- **Port**: `80` (HTTP) and `443` (HTTPS)
|
||||
- **Host name**: `tuneripper-api.vrba.one`
|
||||
4. Click **"OK"**
|
||||
|
||||
### 5.3 Create Blazor WebAssembly Application
|
||||
1. Right-click **"Sites"** ? **"Add Website..."**
|
||||
2. Configure the Blazor site:
|
||||
- **Site name**: `TuneRipper App`
|
||||
- **Physical path**: `C:\inetpub\wwwroot\TuneRipper`
|
||||
- **Port**: `80` (HTTP) and `443` (HTTPS)
|
||||
- **Host name**: `tuneripper.vrba.one`
|
||||
3. Click **"OK"**
|
||||
|
||||
### 5.4 Configure Application Pool for API (.NET 10 Specific)
|
||||
1. Click **"Application Pools"** in the left panel
|
||||
2. Find the application pool for **TuneRipper API** (usually has the same name)
|
||||
3. Right-click ? **"Advanced Settings..."**
|
||||
4. Set the following **.NET 10 specific settings**:
|
||||
- **.NET CLR Version**: `No Managed Code` (This is correct for .NET 10!)
|
||||
- **Managed Pipeline Mode**: `Integrated`
|
||||
- **Start Mode**: `OnDemand`
|
||||
- **Process Identity**: `ApplicationPoolIdentity`
|
||||
- **Load User Profile**: `True` (important for .NET 10)
|
||||
- **Idle Time-out (minutes)**: `20` or `0` (no timeout for testing)
|
||||
5. Click **"OK"**
|
||||
|
||||
### 5.5 Verify ASP.NET Core Module for API Site
|
||||
1. Select your **TuneRipper API** site in IIS Manager
|
||||
2. Double-click **"Modules"**
|
||||
3. Ensure **AspNetCoreModuleV2** is present and enabled
|
||||
4. If not present, the Hosting Bundle installation may have failed
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Configure SSL Certificates with Let's Encrypt
|
||||
|
||||
### 6.1 Using win-acme (Recommended)
|
||||
1. Open **Command Prompt as Administrator**
|
||||
2. Navigate to win-acme directory:
|
||||
```cmd
|
||||
cd C:\win-acme\
|
||||
```
|
||||
3. Run win-acme and create certificates for both domains:
|
||||
```cmd
|
||||
wacs.exe --target iis --siteid 1 --commonname tuneripper.vrba.one
|
||||
wacs.exe --target iis --siteid 2 --commonname tuneripper-api.vrba.one
|
||||
```
|
||||
4. Follow the prompts to:
|
||||
- Select the IIS sites
|
||||
- Validate domain ownership
|
||||
- Install certificates
|
||||
- Set up automatic renewal
|
||||
|
||||
### 6.2 Configure HTTPS Bindings in IIS
|
||||
1. In IIS Manager, select **TuneRipper App** site
|
||||
2. Click **"Bindings..."** in the Actions panel
|
||||
3. Click **"Add..."**
|
||||
4. Configure HTTPS binding:
|
||||
- **Type**: `https`
|
||||
- **Port**: `443`
|
||||
- **Host name**: `tuneripper.vrba.one`
|
||||
- **SSL certificate**: Select the Let's Encrypt certificate
|
||||
5. Repeat for **TuneRipper API** site with `tuneripper-api.vrba.one`
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Configure Production Settings
|
||||
|
||||
### 7.1 Update API Configuration for Production
|
||||
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
|
||||
2. Edit `appsettings.json`:
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"TuneRipper.Api.Services.VideoService": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "tuneripper-api.vrba.one",
|
||||
"ApiSettings": {
|
||||
"BaseUrl": "https://tuneripper-api.vrba.one",
|
||||
"HttpBaseUrl": "https://tuneripper-api.vrba.one",
|
||||
"TimeoutSeconds": 300,
|
||||
"EnableLogging": true,
|
||||
"RetryAttempts": 3,
|
||||
"RetryDelaySeconds": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 Update CORS for Production Domains
|
||||
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
|
||||
2. If you need to restrict CORS (optional), modify the API's `Program.cs`:
|
||||
```csharp
|
||||
// Update CORS policy for production
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("ProductionPolicy", policy =>
|
||||
{
|
||||
policy.WithOrigins(
|
||||
"https://tuneripper.vrba.one",
|
||||
"https://tuneripper-api.vrba.one"
|
||||
)
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
// Use the production policy
|
||||
app.UseCors("ProductionPolicy");
|
||||
```
|
||||
|
||||
**Note**: The current CORS configuration uses `AllowAnyOrigin()` which will work fine with your subdomains without changes. The above restriction is optional for enhanced security.
|
||||
|
||||
### 7.3 Update Blazor App Configuration
|
||||
1. Navigate to `C:\inetpub\wwwroot\TuneRipper\`
|
||||
2. Update `appsettings.json`:
|
||||
```json
|
||||
{
|
||||
"ApiSettings": {
|
||||
"BaseUrl": "https://tuneripper-api.vrba.one",
|
||||
"HttpBaseUrl": "https://tuneripper-api.vrba.one",
|
||||
"TimeoutSeconds": 300,
|
||||
"EnableLogging": false,
|
||||
"RetryAttempts": 3,
|
||||
"RetryDelaySeconds": 2
|
||||
},
|
||||
"AppSettings": {
|
||||
"AppName": "TuneRipper",
|
||||
"Version": "1.0.0",
|
||||
"Environment": "Production",
|
||||
"EnableDetailedErrors": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.4 Update API Root Endpoint URLs
|
||||
1. Navigate to `C:\inetpub\wwwroot\TuneRipperApi\`
|
||||
2. If needed, update the root endpoint in `Program.cs` to show production URLs:
|
||||
```csharp
|
||||
urls = new
|
||||
{
|
||||
https = "https://tuneripper-api.vrba.one",
|
||||
app = "https://tuneripper.vrba.one"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 8: Verify Web Configuration Files
|
||||
|
||||
> **? Good News**: The `web.config` files are now included in both projects and will be automatically deployed during publish!
|
||||
|
||||
### 8.1 API web.config (Auto-deployed)
|
||||
The API project now includes a `web.config` file that will be automatically copied during publish. It includes:
|
||||
- **HTTPS redirection** for production security
|
||||
- **ASP.NET Core hosting** configuration for IIS
|
||||
- **Security headers** for production
|
||||
- **Environment variables** set to Production
|
||||
|
||||
**Location after publish**: `C:\inetpub\wwwroot\TuneRipperApi\web.config`
|
||||
|
||||
### 8.2 Blazor WebAssembly web.config (Auto-deployed)
|
||||
The Blazor project now includes a `web.config` file that will be automatically copied during publish. It includes:
|
||||
- **HTTPS redirection** for production security
|
||||
- **SPA routing support** for client-side navigation
|
||||
- **MIME type mappings** for .wasm and .dll files
|
||||
- **Security headers** for production
|
||||
|
||||
**Location after publish**: `C:\inetpub\wwwroot\TuneRipper\web.config`
|
||||
|
||||
### 8.3 Manual Verification (Optional)
|
||||
After deployment, you can verify the files are present:
|
||||
1. Check API web.config: `C:\inetpub\wwwroot\TuneRipperApi\web.config`
|
||||
2. Check Blazor web.config: `C:\inetpub\wwwroot\TuneRipper\web.config`
|
||||
|
||||
> **Note**: These files are now version-controlled and automatically deployed. No manual configuration needed!
|
||||
|
||||
---
|
||||
|
||||
## Step 9: Set Permissions
|
||||
|
||||
### 9.1 Configure Folder Permissions
|
||||
1. Right-click `C:\inetpub\wwwroot\TuneRipperApi\wwwroot\downloads`
|
||||
2. Select **"Properties"** ? **"Security"** tab
|
||||
3. Click **"Edit..."** ? **"Add..."**
|
||||
4. Type: `IIS_IUSRS` and click **"Check Names"** ? **"OK"**
|
||||
5. Select **IIS_IUSRS** and check:
|
||||
- ? **Full Control**
|
||||
- ? **Modify**
|
||||
- ? **Read & Execute**
|
||||
- ? **Write**
|
||||
6. Click **"OK"** to save
|
||||
|
||||
### 9.2 Set Application Pool Identity Permissions
|
||||
1. Right-click `C:\inetpub\wwwroot\TuneRipperApi`
|
||||
2. **Properties** ? **Security** ? **Edit** ? **Add**
|
||||
3. Type: `IIS AppPool\TuneRipper API` ? **Check Names** ? **OK**
|
||||
4. Grant **Read & Execute** permissions
|
||||
5. Click **OK**
|
||||
|
||||
---
|
||||
|
||||
## Step 10: Test Deployment
|
||||
|
||||
### 10.1 Test .NET 10 Runtime in IIS
|
||||
1. Start both websites in IIS Manager
|
||||
2. Check Application Pool status - should be **"Started"**
|
||||
3. If Application Pool keeps stopping, check Event Viewer for errors
|
||||
|
||||
### 10.2 Test Production URLs
|
||||
1. Open a web browser
|
||||
2. Navigate to: `https://tuneripper-api.vrba.one/api/health`
|
||||
3. You should see a JSON health check response
|
||||
4. Test the root endpoint: `https://tuneripper-api.vrba.one/`
|
||||
5. Verify the API information is displayed
|
||||
|
||||
### 10.3 Test Blazor WebAssembly App
|
||||
1. Navigate to: `https://tuneripper.vrba.one`
|
||||
2. The TuneRipper application should load
|
||||
3. Check browser developer tools (F12) for any loading errors
|
||||
4. Test the YouTube URL input functionality
|
||||
|
||||
### 10.4 Test End-to-End Functionality
|
||||
1. In the Blazor app, enter a YouTube URL
|
||||
2. Click **"Download MP3"**
|
||||
3. Monitor the processing progress
|
||||
4. Verify the file download works
|
||||
|
||||
### 10.5 Test SSL Certificates
|
||||
1. Check certificate validity in browser
|
||||
2. Verify automatic HTTP to HTTPS redirection
|
||||
3. Test certificate auto-renewal (win-acme sets up scheduled tasks)
|
||||
|
||||
---
|
||||
|
||||
## Step 11: Troubleshooting
|
||||
|
||||
### 11.1 Common .NET 10 Issues
|
||||
|
||||
#### Application Pool Keeps Stopping
|
||||
**Problem**: Application pool stops immediately after starting
|
||||
**Solutions**:
|
||||
1. Check Event Viewer: `Windows Logs` ? `Application` and `System`
|
||||
2. Look for ASP.NET Core errors or .NET runtime issues
|
||||
3. Verify .NET 10 Hosting Bundle is properly installed:
|
||||
```cmd
|
||||
dotnet --list-runtimes
|
||||
```
|
||||
4. Ensure `web.config` has correct `processPath` and `arguments`
|
||||
5. Check Application Pool settings:
|
||||
- .NET CLR Version = "No Managed Code"
|
||||
- Managed Pipeline Mode = "Integrated"
|
||||
|
||||
#### SSL Certificate Issues
|
||||
**Problem**: SSL certificate not working or expired
|
||||
**Solutions**:
|
||||
1. Check certificate binding in IIS Manager
|
||||
2. Verify Let's Encrypt certificate renewal:
|
||||
```cmd
|
||||
# For win-acme
|
||||
wacs.exe --list
|
||||
|
||||
# For certbot
|
||||
certbot certificates
|
||||
```
|
||||
3. Check Windows Task Scheduler for renewal tasks
|
||||
4. Manually renew if needed:
|
||||
```cmd
|
||||
# For win-acme
|
||||
wacs.exe --renew
|
||||
|
||||
# For certbot
|
||||
certbot renew
|
||||
```
|
||||
|
||||
#### CORS Errors
|
||||
**Problem**: Cross-origin requests blocked
|
||||
**Solutions**:
|
||||
1. Verify CORS configuration in `Program.cs`
|
||||
2. Current configuration uses `AllowAnyOrigin()` which should work
|
||||
3. If you implemented production CORS restrictions, ensure domains are correctly specified
|
||||
4. Check browser console for specific CORS error messages
|
||||
|
||||
#### 500 Internal Server Error
|
||||
**Problem**: HTTP 500 error when accessing API
|
||||
**Solutions**:
|
||||
1. Enable detailed errors in `web.config`:
|
||||
```xml
|
||||
<aspNetCore processPath="dotnet" arguments=".\TuneRipper.Api.dll"
|
||||
stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout"
|
||||
hostingModel="inprocess">
|
||||
<environmentVariables>
|
||||
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
|
||||
</environmentVariables>
|
||||
</aspNetCore>
|
||||
```
|
||||
2. Create `logs` folder in API directory
|
||||
3. Check stdout logs for detailed error information
|
||||
4. Verify all .NET 10 dependencies are published
|
||||
|
||||
#### Blazor WebAssembly Loading Issues
|
||||
**Problem**: Blazor app shows loading indefinitely
|
||||
**Solutions**:
|
||||
1. Check browser console (F12) for JavaScript errors
|
||||
2. Verify all `.wasm` and `.dll` files are present in `_framework` folder
|
||||
3. Check that `dotnet.js` and `blazor.webassembly.js` are loading
|
||||
4. Ensure proper MIME types in `web.config`
|
||||
5. Verify API base URL is correctly configured in `appsettings.json`
|
||||
|
||||
### 11.2 Verification Commands
|
||||
```cmd
|
||||
# Check .NET installation (Hosting Bundle should show runtimes, SDK not required)
|
||||
dotnet --list-runtimes
|
||||
|
||||
# Check IIS status
|
||||
iisreset /status
|
||||
|
||||
# List IIS sites
|
||||
%windir%\system32\inetsrv\appcmd.exe list sites
|
||||
|
||||
# Check Application Pools
|
||||
%windir%\system32\inetsrv\appcmd.exe list appPools
|
||||
|
||||
# Verify ASP.NET Core Module (Critical for .NET 10)
|
||||
%windir%\system32\inetsrv\appcmd.exe list modules | findstr AspNet
|
||||
|
||||
# Check SSL certificates
|
||||
certlm.msc
|
||||
|
||||
# Test HTTPS connectivity
|
||||
curl -I https://tuneripper-api.vrba.one/api/health
|
||||
curl -I https://tuneripper.vrba.one
|
||||
```
|
||||
|
||||
### 11.3 Log Locations
|
||||
- **IIS Logs**: `C:\inetpub\logs\LogFiles\W3SVC1\` (and W3SVC2, etc.)
|
||||
- **Windows Event Log**: Event Viewer ? Application and System logs
|
||||
- **ASP.NET Core stdout logs**: `C:\inetpub\wwwroot\TuneRipperApi\logs\` (if enabled)
|
||||
- **Application-specific logs**: Configure in `appsettings.json`
|
||||
- **Let's Encrypt Logs**:
|
||||
- win-acme: `C:\win-acme\logs\`
|
||||
- certbot: `C:\Certbot\log\`
|
||||
|
||||
---
|
||||
|
||||
## Step 12: Security Considerations
|
||||
|
||||
### 12.1 Production Security
|
||||
1. **SSL/TLS**: Certificates automatically managed by Let's Encrypt
|
||||
2. **HTTPS Enforcement**: Configured in `web.config` for automatic redirection
|
||||
3. **CORS**: Current configuration uses `AllowAnyOrigin()` (works with subdomains)
|
||||
4. **Security Headers**: Added to `web.config` (X-Frame-Options, etc.)
|
||||
5. **File Upload Limits**: Configure maximum file sizes if needed
|
||||
6. **Rate Limiting**: Consider implementing rate limiting for API endpoints
|
||||
7. **Update .NET Regularly**: Keep .NET 10 runtime updated via Hosting Bundle
|
||||
|
||||
### 12.2 Firewall Configuration
|
||||
1. Open Windows Defender Firewall
|
||||
2. Create inbound rules for HTTP (80) and HTTPS (443) ports
|
||||
3. Block development ports (7160, 8080) from external access
|
||||
4. Configure network access as needed
|
||||
|
||||
### 12.3 CORS Security Analysis
|
||||
The current CORS configuration in your API uses:
|
||||
```csharp
|
||||
policy.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
```
|
||||
|
||||
**? This will work perfectly with your subdomain setup** because:
|
||||
- `AllowAnyOrigin()` permits requests from any domain
|
||||
- Your Blazor app at `https://tuneripper.vrba.one` can call API at `https://tuneripper-api.vrba.one`
|
||||
- No CORS configuration changes are required
|
||||
|
||||
**For enhanced security (optional)**, you could restrict to specific domains as shown in Step 7.2.
|
||||
|
||||
---
|
||||
|
||||
## Step 13: Maintenance
|
||||
|
||||
### 13.1 Regular Tasks
|
||||
- Monitor disk space in downloads folder
|
||||
- Update yt-dlp.exe regularly for YouTube compatibility
|
||||
- Check for .NET 10 updates and security patches
|
||||
- Review and rotate log files
|
||||
- Monitor application pool health
|
||||
- **Monitor SSL certificate renewals** (should be automatic)
|
||||
|
||||
### 13.2 SSL Certificate Maintenance
|
||||
- **win-acme**: Automatic renewal via Windows Task Scheduler
|
||||
- **certbot**: Set up automatic renewal:
|
||||
```cmd
|
||||
# Add to Task Scheduler to run twice daily
|
||||
certbot renew --quiet
|
||||
```
|
||||
|
||||
### 13.3 Updating .NET 10
|
||||
When new .NET 10 updates are released:
|
||||
1. Download and install **new .NET 10 Hosting Bundle** (SDK not required)
|
||||
2. Restart IIS: `iisreset`
|
||||
3. Test application functionality
|
||||
4. Update applications if needed (rebuild only if breaking changes)
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Your TuneRipper application should now be successfully deployed on IIS with Windows 11 using .NET 10, complete with production HTTPS via Let's Encrypt.
|
||||
|
||||
**Production URLs:**
|
||||
- **API**: `https://tuneripper-api.vrba.one`
|
||||
- **Blazor App**: `https://tuneripper.vrba.one`
|
||||
|
||||
**Key Production Features:**
|
||||
- ? **Automatic HTTPS** with Let's Encrypt certificates
|
||||
- ? **Automatic HTTP?HTTPS redirection**
|
||||
- ? **CORS compatibility** with subdomain setup
|
||||
- ? **Security headers** configured
|
||||
- ? **Automatic certificate renewal** set up
|
||||
|
||||
## CORS Compatibility Summary
|
||||
|
||||
### ? **Current CORS Configuration Works Perfect**
|
||||
Your existing API CORS setup using `AllowAnyOrigin()` will work seamlessly with:
|
||||
- `https://tuneripper.vrba.one` ? `https://tuneripper-api.vrba.one`
|
||||
- No code changes required
|
||||
- Cross-subdomain requests allowed
|
||||
|
||||
### ?? **Optional Security Enhancement**
|
||||
For production, you can optionally restrict CORS to specific domains (see Step 7.2), but it's not required for functionality.
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
```cmd
|
||||
# Check .NET 10 runtime installation (production)
|
||||
dotnet --list-runtimes
|
||||
|
||||
# Restart IIS
|
||||
iisreset
|
||||
|
||||
# Verify FFmpeg
|
||||
ffmpeg -version
|
||||
|
||||
# Test production endpoints
|
||||
curl https://tuneripper-api.vrba.one/api/health
|
||||
curl -I https://tuneripper.vrba.one
|
||||
|
||||
# Check SSL certificates
|
||||
certlm.msc
|
||||
|
||||
# View IIS processes
|
||||
tasklist | findstr w3wp
|
||||
|
||||
# Check Application Pool status
|
||||
%windir%\system32\inetsrv\appcmd.exe list appPools /text:name,state
|
||||
|
||||
# Renew SSL certificates manually
|
||||
wacs.exe --renew
|
||||
# or
|
||||
certbot renew
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*This guide includes production-ready HTTPS setup with Let's Encrypt for the subdomain configuration: `https://tuneripper.vrba.one` and `https://tuneripper-api.vrba.one`. The existing CORS configuration will work without modifications.*
|
||||
@@ -0,0 +1,298 @@
|
||||
# TuneRipper - YouTube to MP3 Converter
|
||||
|
||||
A modern Blazor WebAssembly application with ASP.NET Core API for converting YouTube videos to MP3 files using yt-dlp.
|
||||
|
||||
## ?? Overview
|
||||
|
||||
TuneRipper is a full-stack web application that allows users to convert YouTube videos to MP3 format. It features a responsive Blazor WebAssembly frontend and a robust ASP.NET Core API backend with real-time progress monitoring.
|
||||
|
||||
## ??? Architecture
|
||||
|
||||
### Projects Structure
|
||||
```
|
||||
TuneRipper/
|
||||
??? TuneRipper/ # Blazor WebAssembly Client
|
||||
??? TuneRipper.Api/ # ASP.NET Core API
|
||||
??? TuneRipper.Shared/ # Shared Models & Configuration
|
||||
??? DEPLOYMENT_GUIDE_IIS_Windows11.md
|
||||
```
|
||||
|
||||
### Technology Stack
|
||||
- **.NET 10** - Latest .NET framework
|
||||
- **Blazor WebAssembly** - Modern SPA framework
|
||||
- **ASP.NET Core API** - RESTful backend services
|
||||
- **yt-dlp** - YouTube video processing
|
||||
- **FFmpeg** - Audio conversion
|
||||
- **IIS** - Production deployment platform
|
||||
|
||||
## ?? Quick Start
|
||||
|
||||
### Prerequisites
|
||||
1. **.NET 10 SDK** installed
|
||||
2. **yt-dlp.exe** (automatically placed in API wwwroot)
|
||||
3. **FFmpeg** available in system PATH
|
||||
|
||||
### Development Setup
|
||||
|
||||
#### 1. Clone the Repository
|
||||
```bash
|
||||
git clone https://git.vrba.one/TuneRipper.git
|
||||
cd TuneRipper
|
||||
```
|
||||
|
||||
#### 2. Start the API
|
||||
```bash
|
||||
cd TuneRipper.Api
|
||||
dotnet run
|
||||
```
|
||||
API will be available at:
|
||||
- **HTTPS**: https://localhost:7160
|
||||
- **HTTP**: http://localhost:5112
|
||||
|
||||
#### 3. Start the Blazor WebAssembly App
|
||||
```bash
|
||||
cd TuneRipper
|
||||
dotnet run
|
||||
```
|
||||
App will be available at: https://localhost:7070
|
||||
|
||||
### Quick Testing
|
||||
1. Navigate to the Blazor app
|
||||
2. Enter a YouTube URL
|
||||
3. Click "Download MP3"
|
||||
4. Monitor real-time progress
|
||||
5. Download the converted file
|
||||
|
||||
## ?? File Management System
|
||||
|
||||
### GUID-Based Naming
|
||||
Downloaded files use the format: **`{jobId}_{title}.mp3`**
|
||||
|
||||
**Examples:**
|
||||
- `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3`
|
||||
- `6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3`
|
||||
|
||||
**Benefits:**
|
||||
- ? **Unique Identification**: No filename conflicts
|
||||
- ? **Direct Job Mapping**: Easy file lookup using GUID
|
||||
- ? **User-Friendly Downloads**: Converted to readable names
|
||||
- ? **Secure Access**: Job ID acts as access token
|
||||
|
||||
### File Storage
|
||||
- **Location**: `TuneRipper.Api/wwwroot/downloads/`
|
||||
- **Access**: Via API endpoints or direct static file serving
|
||||
- **Cleanup**: Automated cleanup by job ID pattern
|
||||
|
||||
## ?? API Workflow
|
||||
|
||||
### 1. Start Processing
|
||||
```http
|
||||
POST /api/video/process
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"format": "mp3",
|
||||
"quality": "128"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Monitor Progress
|
||||
```http
|
||||
GET /api/video/status/{jobId}
|
||||
```
|
||||
Returns real-time progress with video details.
|
||||
|
||||
### 3. Download Result
|
||||
```http
|
||||
GET /api/download/{jobId}
|
||||
```
|
||||
Returns MP3 file with user-friendly filename.
|
||||
|
||||
## ?? Progress Monitoring
|
||||
|
||||
Real-time progress updates from yt-dlp processing:
|
||||
- **5-15%**: Fetching video details
|
||||
- **15-70%**: Downloading audio stream
|
||||
- **70-85%**: Converting to MP3 format
|
||||
- **85-95%**: Finalizing and cleanup
|
||||
- **100%**: Ready for download
|
||||
|
||||
## ??? Development
|
||||
|
||||
### API Endpoints
|
||||
- **Health Check**: `GET /api/health`
|
||||
- **Process Video**: `POST /api/video/process`
|
||||
- **Check Status**: `GET /api/video/status/{jobId}`
|
||||
- **Get Result**: `GET /api/video/result/{jobId}`
|
||||
- **Download File**: `GET /api/download/{jobId}`
|
||||
- **List Jobs**: `GET /api/video/jobs`
|
||||
|
||||
### Configuration
|
||||
Update `appsettings.json` for environment-specific settings:
|
||||
```json
|
||||
{
|
||||
"ApiSettings": {
|
||||
"BaseUrl": "https://localhost:7160",
|
||||
"TimeoutSeconds": 300,
|
||||
"EnableLogging": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Testing
|
||||
Use the provided HTTP test file:
|
||||
```bash
|
||||
# Open TuneRipper.Api/api-tests.http in VS Code or Visual Studio
|
||||
```
|
||||
|
||||
## ?? Deployment
|
||||
|
||||
### IIS on Windows 11 (Recommended)
|
||||
Follow the comprehensive deployment guide:
|
||||
```bash
|
||||
# See DEPLOYMENT_GUIDE_IIS_Windows11.md for detailed instructions
|
||||
```
|
||||
|
||||
**Key Deployment Steps:**
|
||||
1. Install .NET 10 Hosting Bundle for IIS
|
||||
2. Enable IIS with ASP.NET Core support
|
||||
3. Publish applications using Release configuration
|
||||
4. Configure IIS sites and application pools
|
||||
5. Set proper file permissions
|
||||
6. Test end-to-end functionality
|
||||
|
||||
### Docker (Alternative)
|
||||
```dockerfile
|
||||
# Dockerfile examples available for containerized deployment
|
||||
```
|
||||
|
||||
## ?? Configuration Details
|
||||
|
||||
### Required Tools
|
||||
- **yt-dlp.exe**: Place in `TuneRipper.Api/wwwroot/`
|
||||
- **FFmpeg**: Add to system PATH for audio conversion
|
||||
|
||||
### Environment Variables
|
||||
- `ASPNETCORE_ENVIRONMENT`: Development/Production
|
||||
- `ASPNETCORE_URLS`: Custom binding URLs
|
||||
|
||||
### CORS Configuration
|
||||
API is configured to allow Blazor WebAssembly client access:
|
||||
```csharp
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("BlazorPolicy", policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## ?? Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### API Not Starting
|
||||
```bash
|
||||
# Check .NET installation
|
||||
dotnet --version
|
||||
|
||||
# Trust development certificates
|
||||
dotnet dev-certs https --trust
|
||||
```
|
||||
|
||||
#### yt-dlp Not Found
|
||||
- Verify `yt-dlp.exe` is in `TuneRipper.Api/wwwroot/`
|
||||
- Check file permissions
|
||||
- Ensure downloads directory exists
|
||||
|
||||
#### FFmpeg Issues
|
||||
```bash
|
||||
# Verify FFmpeg installation
|
||||
ffmpeg -version
|
||||
|
||||
# Add to PATH if needed
|
||||
```
|
||||
|
||||
#### CORS Errors
|
||||
- Verify API base URL configuration in Blazor app
|
||||
- Check CORS policy settings
|
||||
- Ensure API is running on expected port
|
||||
|
||||
### Debug Logging
|
||||
Enable detailed logging in `appsettings.json`:
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"TuneRipper.Api.Services.VideoService": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ?? Security Considerations
|
||||
|
||||
### Production Deployment
|
||||
- **HTTPS Only**: Configure SSL certificates
|
||||
- **CORS Restrictions**: Limit allowed origins
|
||||
- **Rate Limiting**: Implement API rate limiting
|
||||
- **File Cleanup**: Set up automated cleanup jobs
|
||||
- **Access Control**: Consider authentication for production
|
||||
|
||||
### File Security
|
||||
- Job IDs provide secure file access
|
||||
- No directory traversal vulnerabilities
|
||||
- Automatic cleanup prevents disk space issues
|
||||
|
||||
## ?? Performance Optimization
|
||||
|
||||
### Recommended Settings
|
||||
- **Application Pool**: Configure for .NET 10
|
||||
- **File Storage**: Consider cloud storage for scale
|
||||
- **Caching**: Implement response caching where appropriate
|
||||
- **Monitoring**: Set up application insights
|
||||
|
||||
### Scaling Considerations
|
||||
- GUID-based naming supports distributed environments
|
||||
- Stateless API design enables horizontal scaling
|
||||
- Consider queue-based processing for high load
|
||||
|
||||
## ?? Maintenance
|
||||
|
||||
### Regular Tasks
|
||||
- Update yt-dlp.exe for YouTube compatibility
|
||||
- Monitor disk space in downloads directory
|
||||
- Check for .NET 10 security updates
|
||||
- Review and rotate log files
|
||||
|
||||
### Monitoring
|
||||
- Application pool health
|
||||
- File system usage
|
||||
- API response times
|
||||
- Error rates and patterns
|
||||
|
||||
## ?? Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Test thoroughly
|
||||
5. Submit a pull request
|
||||
|
||||
## ?? License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
|
||||
## ?? Related Files
|
||||
|
||||
- **Deployment Guide**: `DEPLOYMENT_GUIDE_IIS_Windows11.md`
|
||||
- **API Tests**: `TuneRipper.Api/api-tests.http`
|
||||
- **Project Files**: `*.csproj` in each project directory
|
||||
|
||||
---
|
||||
|
||||
**Built with ?? using .NET 10, Blazor WebAssembly, and modern web technologies.**
|
||||
@@ -1,84 +0,0 @@
|
||||
# TuneRipper API
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Starting the API
|
||||
|
||||
**Option 1: Using the start script (Windows)**
|
||||
```cmd
|
||||
cd TuneRipper.Api
|
||||
start-api.bat
|
||||
```
|
||||
|
||||
**Option 2: Using the start script (Linux/Mac)**
|
||||
```bash
|
||||
cd TuneRipper.Api
|
||||
chmod +x start-api.sh
|
||||
./start-api.sh
|
||||
```
|
||||
|
||||
**Option 3: Manual start**
|
||||
```cmd
|
||||
cd TuneRipper.Api
|
||||
dotnet run
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
Once running, the API will be available at:
|
||||
- **HTTPS**: https://localhost:7160
|
||||
- **HTTP**: http://localhost:5112
|
||||
|
||||
### Testing the API
|
||||
|
||||
1. **Start the API** using one of the methods above
|
||||
2. **Open the HTTP test file**: `TuneRipper.Api/api-tests.http`
|
||||
3. **Run the connectivity tests first** to verify the API is responding
|
||||
4. **Use the main API tests** once connectivity is confirmed
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### "This localhost page can't be found" errors:
|
||||
|
||||
1. **Check if API is running**:
|
||||
- Look for console output showing "Now listening on: https://localhost:7160"
|
||||
- If not running, start it using the methods above
|
||||
|
||||
2. **Try HTTP instead of HTTPS**:
|
||||
- Use `http://localhost:5112` instead of `https://localhost:7160`
|
||||
- Some development environments have HTTPS certificate issues
|
||||
|
||||
3. **Trust development certificates** (for HTTPS):
|
||||
```cmd
|
||||
dotnet dev-certs https --trust
|
||||
```
|
||||
|
||||
4. **Check port availability**:
|
||||
- Make sure ports 7160 and 5112 aren't used by other applications
|
||||
- You can change ports in `Properties/launchSettings.json`
|
||||
|
||||
#### HTTP test file variables not working:
|
||||
|
||||
1. **Copy job IDs manually**:
|
||||
- Run a POST request to start processing
|
||||
- Copy the `fileName` value from the response
|
||||
- Use it in the manual test sections
|
||||
|
||||
2. **Use the troubleshooting section**:
|
||||
- Start with connectivity tests
|
||||
- Use manual GUID replacements if variables fail
|
||||
|
||||
### API Documentation
|
||||
|
||||
When the API is running, you can access:
|
||||
- **Root endpoint**: https://localhost:7160/ (lists available endpoints)
|
||||
- **OpenAPI spec**: https://localhost:7160/openapi/v1.json
|
||||
- **Health check**: https://localhost:7160/api/health
|
||||
|
||||
### Development
|
||||
|
||||
The API includes:
|
||||
- Automatic reload on code changes (when using `dotnet run`)
|
||||
- Detailed logging in the console
|
||||
- CORS enabled for Blazor WebAssembly client
|
||||
- OpenAPI/Swagger support for API documentation
|
||||
@@ -1,296 +0,0 @@
|
||||
# TuneRipper API - yt-dlp Integration
|
||||
|
||||
## Overview
|
||||
|
||||
The TuneRipper API has been updated to use `yt-dlp.exe` for real YouTube video processing with progress monitoring. Videos are downloaded and converted to MP3 files, stored in the `wwwroot/downloads` directory with a GUID-based filename format, and served directly through the API.
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
1. **.NET 10** installed
|
||||
2. **yt-dlp.exe** placed in `TuneRipper.Api/wwwroot/yt-dlp.exe`
|
||||
3. **ffmpeg** available in PATH (required by yt-dlp for audio conversion)
|
||||
|
||||
### File Structure
|
||||
```
|
||||
TuneRipper.Api/
|
||||
??? wwwroot/
|
||||
? ??? yt-dlp.exe # YouTube downloader executable
|
||||
? ??? downloads/ # Downloaded MP3 files (auto-created)
|
||||
??? Controllers/
|
||||
??? Services/
|
||||
??? Program.cs
|
||||
```
|
||||
|
||||
## Filename Format
|
||||
|
||||
Downloaded files use the structured format: **`{jobId}_{title}.mp3`**
|
||||
|
||||
### Format Breakdown:
|
||||
- **`{jobId}`**: GUID identifier for the processing job (e.g., `550e8400-e29b-41d4-a716-446655440000`)
|
||||
- **`_{title}`**: Sanitized video title with spaces replaced by underscores
|
||||
- **`.mp3`**: Audio format extension
|
||||
|
||||
### Examples:
|
||||
- `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3`
|
||||
- `6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3`
|
||||
- `6ba7b811-9dad-11d1-80b4-00c04fd430c8_Amazing_Guitar_Solo_Performance.mp3`
|
||||
|
||||
### Benefits:
|
||||
- **Unique Identification**: GUID ensures no filename conflicts
|
||||
- **Direct Job Mapping**: Easy file lookup using job ID
|
||||
- **Human Readable**: Title part provides context
|
||||
- **System Friendly**: Sanitized for filesystem compatibility
|
||||
|
||||
### Title Sanitization:
|
||||
- Invalid filename characters are replaced with safe alternatives
|
||||
- Spaces become underscores (`_`)
|
||||
- Special characters: `< > | : * ? " /` are replaced with safe chars
|
||||
- Maximum title length: 50 characters
|
||||
- Fallback to "video" if title cannot be determined
|
||||
|
||||
## Key Changes
|
||||
|
||||
### 1. Program.cs Updates
|
||||
- Added `UseStaticFiles()` middleware for serving downloaded files
|
||||
- Added `AddHttpClient()` for VideoService HTTP requests
|
||||
- Updated logging and endpoint information
|
||||
|
||||
### 2. VideoService Updates
|
||||
- **GUID-Based Filenames**: Uses job ID as primary identifier in filename
|
||||
- **Title Sanitization**: Converts video titles to safe filenames
|
||||
- **Direct Job Mapping**: Files can be found using `{jobId}_*.*` pattern
|
||||
- **Real yt-dlp Integration**: Uses actual yt-dlp.exe with progress monitoring
|
||||
- **Progress Parsing**: Real-time progress from yt-dlp output streams
|
||||
- **Error Handling**: Comprehensive error handling with 5-minute timeout
|
||||
|
||||
### 3. VideoController Updates
|
||||
- Passes job ID to VideoService for filename generation
|
||||
- Uses actual yt-dlp processing instead of simulation
|
||||
- Stores downloaded file information with GUID-based naming
|
||||
- Returns real download URLs for completed files
|
||||
|
||||
### 4. DownloadController Updates
|
||||
- **Precise Job Lookup**: Uses `{jobId}_*.*` pattern for exact file matching
|
||||
- **User-Friendly Downloads**: Converts filenames back to readable format
|
||||
- **Example**: `550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3` ? `Rick Astley Never Gonna Give You Up.mp3`
|
||||
- **Reliable File Operations**: No ambiguity in file identification
|
||||
- Serves actual MP3 files from `wwwroot/downloads/`
|
||||
- Proper MIME type detection for audio files
|
||||
|
||||
## API Workflow
|
||||
|
||||
### 1. Start Processing
|
||||
```http
|
||||
POST /api/video/process
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"format": "mp3",
|
||||
"quality": "128"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Processing started",
|
||||
"fileName": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"downloadUrl": null,
|
||||
"videoDetails": null
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Monitor Progress
|
||||
```http
|
||||
GET /api/video/status/550e8400-e29b-41d4-a716-446655440000
|
||||
```
|
||||
|
||||
**Response (Processing):**
|
||||
```json
|
||||
{
|
||||
"percentageComplete": 45,
|
||||
"status": "Processing",
|
||||
"message": "Downloading audio...",
|
||||
"videoDetails": {
|
||||
"id": "dQw4w9WgXcQ",
|
||||
"title": "Rick Astley - Never Gonna Give You Up",
|
||||
"thumbnailUrl": "https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Get Final Result
|
||||
```http
|
||||
GET /api/video/result/550e8400-e29b-41d4-a716-446655440000
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Video processed successfully",
|
||||
"fileName": "550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3",
|
||||
"downloadUrl": "/downloads/550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3",
|
||||
"videoDetails": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Download File
|
||||
```http
|
||||
GET /api/download/550e8400-e29b-41d4-a716-446655440000
|
||||
```
|
||||
**Response:** Binary MP3 file download with user-friendly filename
|
||||
**Download Name:** `Rick Astley Never Gonna Give You Up.mp3`
|
||||
|
||||
**Alternative Static File Access:**
|
||||
```http
|
||||
GET /downloads/550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3
|
||||
```
|
||||
|
||||
## File Management
|
||||
|
||||
### Download Directory
|
||||
- **Location**: `wwwroot/downloads/`
|
||||
- **Naming Pattern**: `{jobId}_{title}.ext`
|
||||
- **Job Lookup**: Files found using `Directory.GetFiles(dir, "{jobId}_*.*")`
|
||||
- **User Download**: Converted back to readable names
|
||||
- **Cleanup**: Files can be deleted by job ID
|
||||
|
||||
### File Serving Options
|
||||
1. **API Download**: Controlled access via `/api/download/{jobId}` (recommended)
|
||||
- Uses job ID for secure file lookup
|
||||
- Returns user-friendly filename
|
||||
- Proper error handling
|
||||
2. **Static Files**: Direct access via `/downloads/{actual_filename}`
|
||||
- Requires knowing the full filename
|
||||
- Less secure but faster
|
||||
3. **Content-Type**: Automatic detection based on file extension
|
||||
|
||||
### File Operations by Job ID
|
||||
- **Find**: `GET /api/download/info/{jobId}` - Get file metadata
|
||||
- **Download**: `GET /api/download/{jobId}` - Download the file
|
||||
- **Delete**: `DELETE /api/download/{jobId}` - Remove the file
|
||||
|
||||
## Progress Monitoring
|
||||
|
||||
The VideoService monitors yt-dlp output and translates it to progress updates:
|
||||
|
||||
- **5-15%**: Fetching video details
|
||||
- **15-70%**: Downloading audio (yt-dlp download progress × 0.7)
|
||||
- **70-85%**: Converting to MP3 (ffmpeg processing)
|
||||
- **85-95%**: Finalizing (cleanup)
|
||||
- **100%**: Complete
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors:
|
||||
1. **yt-dlp.exe not found**: Ensure yt-dlp.exe is in wwwroot directory
|
||||
2. **ffmpeg not available**: Install ffmpeg and add to PATH
|
||||
3. **Invalid YouTube URL**: URL format validation
|
||||
4. **Download timeout**: 5-minute timeout for processing
|
||||
5. **File not found**: File may have been cleaned up or job ID invalid
|
||||
|
||||
### Error Response Format:
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Error description",
|
||||
"fileName": null,
|
||||
"downloadUrl": null,
|
||||
"videoDetails": null
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### appsettings.json
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"TuneRipper.Api.Services.VideoService": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### yt-dlp Arguments Used:
|
||||
- `--extract-audio`: Extract audio only
|
||||
- `--audio-format mp3`: Convert to MP3
|
||||
- `--audio-quality 0`: Best quality
|
||||
- `--no-playlist`: Single video only
|
||||
- `--no-warnings`: Clean output
|
||||
- `--newline`: Line-by-line progress
|
||||
- `--output "{jobId}_{title}.%(ext)s"`: Uses job ID-based filename
|
||||
|
||||
## Testing
|
||||
|
||||
### Manual Testing:
|
||||
1. Start the API: `dotnet run --project TuneRipper.Api`
|
||||
2. Use API testing tools or the Blazor client
|
||||
3. Check logs for yt-dlp progress
|
||||
4. Verify files in `wwwroot/downloads/` with GUID-based naming
|
||||
|
||||
### Example Test Files:
|
||||
```
|
||||
wwwroot/downloads/
|
||||
??? 550e8400-e29b-41d4-a716-446655440000_Rick_Astley_Never_Gonna_Give_You_Up.mp3
|
||||
??? 6ba7b810-9dad-11d1-80b4-00c04fd430c8_How_to_Build_a_Web_API.mp3
|
||||
??? 6ba7b811-9dad-11d1-80b4-00c04fd430c8_Amazing_Guitar_Solo_Performance.mp3
|
||||
```
|
||||
|
||||
### Health Check:
|
||||
```http
|
||||
GET /api/health
|
||||
```
|
||||
|
||||
### Job Listing:
|
||||
```http
|
||||
GET /api/video/jobs
|
||||
```
|
||||
|
||||
## Production Considerations
|
||||
|
||||
1. **File Storage**: Consider cloud storage for production
|
||||
2. **Cleanup Strategy**: Implement automatic file cleanup/retention using job completion timestamps
|
||||
3. **Security**: Job IDs provide secure file access (no directory traversal)
|
||||
4. **Performance**: Consider queue-based processing for high load
|
||||
5. **Monitoring**: Add detailed logging and metrics
|
||||
6. **Updates**: Keep yt-dlp.exe updated for compatibility
|
||||
7. **Scalability**: GUID-based naming prevents conflicts in distributed systems
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues:
|
||||
1. **Permissions**: Ensure API can write to wwwroot/downloads
|
||||
2. **Antivirus**: yt-dlp.exe may be flagged by antivirus
|
||||
3. **Network**: YouTube may block requests from some IPs
|
||||
4. **Format Support**: Some videos may not support audio extraction
|
||||
5. **Long Titles**: Titles are truncated to 50 characters for filesystem compatibility
|
||||
|
||||
### Debug Logging:
|
||||
Enable debug logging for VideoService to see detailed yt-dlp output:
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"TuneRipper.Api.Services.VideoService": "Debug"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### File Lookup Issues:
|
||||
- Verify job ID matches the GUID format
|
||||
- Check that files exist with the `{jobId}_` prefix
|
||||
- Look at directory contents if files are not found
|
||||
- Ensure proper case sensitivity on Linux systems
|
||||
|
||||
### Advantages of GUID-Based Naming:
|
||||
1. **Unique**: No filename conflicts possible
|
||||
2. **Secure**: Job ID acts as access token
|
||||
3. **Traceable**: Direct mapping from API calls to files
|
||||
4. **Scalable**: Works in distributed environments
|
||||
5. **Clean**: Easy cleanup by job ID pattern
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<location path="." inheritInChildApplications="false">
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="dotnet" arguments=".\TuneRipper.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
|
||||
<environmentVariables>
|
||||
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
|
||||
</environmentVariables>
|
||||
</aspNetCore>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Redirect to HTTPS" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions>
|
||||
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
|
||||
</conditions>
|
||||
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
<!-- Security headers -->
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="X-Content-Type-Options" value="nosniff" />
|
||||
<add name="X-Frame-Options" value="DENY" />
|
||||
<add name="X-XSS-Protection" value="1; mode=block" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
</location>
|
||||
</configuration>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<!-- Force HTTPS -->
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Redirect to HTTPS" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions>
|
||||
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
|
||||
</conditions>
|
||||
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
|
||||
</rule>
|
||||
<rule name="Serve subdir">
|
||||
<match url=".*" />
|
||||
<action type="Rewrite" url="wwwroot\{R:0}" />
|
||||
</rule>
|
||||
<rule name="SPA fallback routing" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="wwwroot\" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
<staticContent>
|
||||
<mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
|
||||
<mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
|
||||
<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
|
||||
</staticContent>
|
||||
<!-- Security headers -->
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="X-Content-Type-Options" value="nosniff" />
|
||||
<add name="X-Frame-Options" value="DENY" />
|
||||
<add name="X-XSS-Protection" value="1; mode=block" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user