Skip to content

Commit

Permalink
ElevenLabs-DotNet 3.0.0
Browse files Browse the repository at this point in the history
Version 3.0.0
- Added ability to specify fully customizable domain proxies
- Added environment variable parsing for ELEVENLABS_API_KEY
- Added SoundEffects API endpoints
- Updated default models
  • Loading branch information
StephenHodgson committed Jul 21, 2024
1 parent c7a2a95 commit 06f49fe
Show file tree
Hide file tree
Showing 41 changed files with 1,175 additions and 234 deletions.
35 changes: 18 additions & 17 deletions ElevenLabs-DotNet-Proxy/ElevenLabs-DotNet-Proxy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,51 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<Authors>Stephen Hodgson</Authors>
<Title>ElevenLabs API Proxy</Title>
<Product>ElevenLabs-DotNet-Proxy</Product>
<PackageId>ElevenLabs-DotNet-Proxy</PackageId>
<RootNamespace>ElevenLabs.Proxy</RootNamespace>
<Description>A simple Proxy API gateway for ElevenLabs-DotNet to make authenticated requests from a front end application without exposing your API keys.</Description>
<Copyright>2024</Copyright>
<PackageProjectUrl>https://github.com/RageAgainstThePixel/ElevenLabs-DotNet</PackageProjectUrl>
<RepositoryUrl>https://github.com/RageAgainstThePixel/ElevenLabs-DotNet</RepositoryUrl>
<PackageTags>ElevenLabs, AI, ML, API, api-proxy, proxy, gateway</PackageTags>
<Title>ElevenLabs API Proxy</Title>
<PackageId>ElevenLabs-DotNet-Proxy</PackageId>
<Version>2.2.2</Version>
<RootNamespace>ElevenLabs.Proxy</RootNamespace>
<PackageReleaseNotes>Version 2.2.2
<PackageIcon>ElevenLabsIcon.png</PackageIcon>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<IncludeSymbols>true</IncludeSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<Version>3.0.0</Version>
<PackageReleaseNotes>
Version 3.0.0
- Renamed ElevenLabsProxyStartup to ElevenLabsProxy
Version 2.2.2
- Updated EndpointRouteBuilder with optional route prefix parameter
Version 2.2.1
- Refactor with modern WebApplication builder
- Added ElevenLabs.Proxy.EndpointRouteBuilder
</PackageReleaseNotes>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<IncludeSymbols>True</IncludeSymbols>
<PackageIcon>ElevenLabsIcon.png</PackageIcon>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ElevenLabs-DotNet\ElevenLabs-DotNet.csproj" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<None Include="..\ElevenLabs-DotNet\Assets\ElevenLabsIcon.png">
<Pack>True</Pack>
<Pack>true</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\LICENSE">
<Pack>True</Pack>
<Pack>true</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<None Update="Readme.md">
<Pack>True</Pack>
<Pack>true</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
Expand Down
114 changes: 114 additions & 0 deletions ElevenLabs-DotNet-Proxy/Proxy/ElevenLabsProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading.Tasks;

namespace ElevenLabs.Proxy
{
/// <summary>
/// Used in ASP.NET Core WebApps to start your own ElevenLabs web api proxy.
/// </summary>
public class ElevenLabsProxy
{
private ElevenLabsClient elevenLabsClient;
private IAuthenticationFilter authenticationFilter;

/// <summary>
/// Configures the <see cref="ElevenLabsClient"/> and <see cref="IAuthenticationFilter"/> services.
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
=> SetupServices(services.BuildServiceProvider());

/// <summary>
/// Configures the <see cref="IApplicationBuilder"/> to handle requests and forward them to OpenAI API.
/// </summary>
/// <param name="app"><see cref="IApplicationBuilder"/>.</param>
/// <param name="env"><see cref="IWebHostEnvironment"/>.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

SetupServices(app.ApplicationServices);

app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/health", HealthEndpoint);
endpoints.MapElevenLabsEndpoints(elevenLabsClient, authenticationFilter);
});
}

/// <summary>
/// Creates a new <see cref="IHost"/> that acts as a proxy web api for ElevenLabs.
/// </summary>
/// <typeparam name="T"><see cref="IAuthenticationFilter"/> type to use to validate your custom issued tokens.</typeparam>
/// <param name="args">Startup args.</param>
/// <param name="elevenLabsClient"><see cref="ElevenLabsClient"/> with configured <see cref="ElevenLabsAuthentication"/> and <see cref="ElevenLabsClientSettings"/>.</param>
public static IHost CreateDefaultHost<T>(string[] args, ElevenLabsClient elevenLabsClient) where T : class, IAuthenticationFilter
=> Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<ElevenLabsProxy>();
webBuilder.ConfigureKestrel(ConfigureKestrel);
})
.ConfigureServices(services =>
{
services.AddSingleton(elevenLabsClient);
services.AddSingleton<IAuthenticationFilter, T>();
}).Build();

/// <summary>
/// Creates a new <see cref="WebApplication"/> that acts as a proxy web api for OpenAI.
/// </summary>
/// <typeparam name="T"><see cref="IAuthenticationFilter"/> type to use to validate your custom issued tokens.</typeparam>
/// <param name="args">Startup args.</param>
/// <param name="elevenLabsClient"><see cref="ElevenLabsClient"/> with configured <see cref="ElevenLabsAuthentication"/> and <see cref="ElevenLabsClientSettings"/>.</param>
public static WebApplication CreateWebApplication<T>(string[] args, ElevenLabsClient elevenLabsClient) where T : class, IAuthenticationFilter
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(ConfigureKestrel);
builder.Services.AddSingleton(elevenLabsClient);
builder.Services.AddSingleton<IAuthenticationFilter, T>();
var app = builder.Build();
var startup = new ElevenLabsProxy();
startup.Configure(app, app.Environment);
return app;
}

private static void ConfigureKestrel(KestrelServerOptions options)
{
options.AllowSynchronousIO = false;
options.Limits.MinRequestBodyDataRate = null;
options.Limits.MinResponseDataRate = null;
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10);
options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(2);
}

private void SetupServices(IServiceProvider serviceProvider)
{
elevenLabsClient = serviceProvider.GetRequiredService<ElevenLabsClient>();
authenticationFilter = serviceProvider.GetRequiredService<IAuthenticationFilter>();
}

private static async Task HealthEndpoint(HttpContext context)
{
// Respond with a 200 OK status code and a plain text message
context.Response.StatusCode = StatusCodes.Status200OK;
const string contentType = "text/plain";
context.Response.ContentType = contentType;
const string content = "OK";
await context.Response.WriteAsync(content);
}
}
}
107 changes: 8 additions & 99 deletions ElevenLabs-DotNet-Proxy/Proxy/ElevenLabsProxyStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,22 @@

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading.Tasks;

namespace ElevenLabs.Proxy
{
/// <summary>
/// Used in ASP.NET Core WebApps to start your own ElevenLabs web api proxy.
/// </summary>
[Obsolete("Use ElevenLabsProxy")]
public class ElevenLabsProxyStartup
{
private ElevenLabsClient elevenLabsClient;
private IAuthenticationFilter authenticationFilter;
public void ConfigureServices(IServiceCollection services) { }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { }

/// <summary>
/// Configures the <see cref="ElevenLabsClient"/> and <see cref="IAuthenticationFilter"/> services.
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
=> SetupServices(services.BuildServiceProvider());
public static IHost CreateDefaultHost<T>(string[] args, ElevenLabsClient elevenLabsClient)
where T : class, IAuthenticationFilter => null;

/// <summary>
/// Configures the <see cref="IApplicationBuilder"/> to handle requests and forward them to OpenAI API.
/// </summary>
/// <param name="app"><see cref="IApplicationBuilder"/>.</param>
/// <param name="env"><see cref="IWebHostEnvironment"/>.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

SetupServices(app.ApplicationServices);

app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/health", HealthEndpoint);
endpoints.MapElevenLabsEndpoints(elevenLabsClient, authenticationFilter);
});
}

/// <summary>
/// Creates a new <see cref="IHost"/> that acts as a proxy web api for ElevenLabs.
/// </summary>
/// <typeparam name="T"><see cref="IAuthenticationFilter"/> type to use to validate your custom issued tokens.</typeparam>
/// <param name="args">Startup args.</param>
/// <param name="elevenLabsClient"><see cref="ElevenLabsClient"/> with configured <see cref="ElevenLabsAuthentication"/> and <see cref="ElevenLabsClientSettings"/>.</param>
public static IHost CreateDefaultHost<T>(string[] args, ElevenLabsClient elevenLabsClient) where T : class, IAuthenticationFilter
=> Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<ElevenLabsProxyStartup>();
webBuilder.ConfigureKestrel(ConfigureKestrel);
})
.ConfigureServices(services =>
{
services.AddSingleton(elevenLabsClient);
services.AddSingleton<IAuthenticationFilter, T>();
}).Build();

/// <summary>
/// Creates a new <see cref="WebApplication"/> that acts as a proxy web api for OpenAI.
/// </summary>
/// <typeparam name="T"><see cref="IAuthenticationFilter"/> type to use to validate your custom issued tokens.</typeparam>
/// <param name="args">Startup args.</param>
/// <param name="elevenLabsClient"><see cref="ElevenLabsClient"/> with configured <see cref="ElevenLabsAuthentication"/> and <see cref="ElevenLabsClientSettings"/>.</param>
public static WebApplication CreateWebApplication<T>(string[] args, ElevenLabsClient elevenLabsClient) where T : class, IAuthenticationFilter
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(ConfigureKestrel);
builder.Services.AddSingleton(elevenLabsClient);
builder.Services.AddSingleton<IAuthenticationFilter, T>();
var app = builder.Build();
var startup = new ElevenLabsProxyStartup();
startup.Configure(app, app.Environment);
return app;
}

private static void ConfigureKestrel(KestrelServerOptions options)
{
options.AllowSynchronousIO = false;
options.Limits.MinRequestBodyDataRate = null;
options.Limits.MinResponseDataRate = null;
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10);
options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(2);
}

private void SetupServices(IServiceProvider serviceProvider)
{
elevenLabsClient = serviceProvider.GetRequiredService<ElevenLabsClient>();
authenticationFilter = serviceProvider.GetRequiredService<IAuthenticationFilter>();
}

private static async Task HealthEndpoint(HttpContext context)
{
// Respond with a 200 OK status code and a plain text message
context.Response.StatusCode = StatusCodes.Status200OK;
const string contentType = "text/plain";
context.Response.ContentType = contentType;
const string content = "OK";
await context.Response.WriteAsync(content);
}
public static WebApplication CreateWebApplication<T>(string[] args, ElevenLabsClient elevenLabsClient)
where T : class, IAuthenticationFilter => null;
}
}
}
4 changes: 2 additions & 2 deletions ElevenLabs-DotNet-Tests-Proxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public override async Task ValidateAuthenticationAsync(IHeaderDictionary request

public static void Main(string[] args)
{
var auth = ElevenLabsAuthentication.LoadFromEnv();
var auth = ElevenLabsAuthentication.LoadFromEnvironment();
var client = new ElevenLabsClient(auth);
ElevenLabsProxyStartup.CreateWebApplication<AuthenticationFilter>(args, client).Run();
ElevenLabsProxy.CreateWebApplication<AuthenticationFilter>(args, client).Run();
}
}
}
1 change: 1 addition & 0 deletions ElevenLabs-DotNet-Tests/AbstractTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ protected AbstractTestFixture()
var settings = new ElevenLabsClientSettings(domain: domain);
var auth = new ElevenLabsAuthentication(TestUserToken);
ElevenLabsClient = new ElevenLabsClient(auth, settings, HttpClient);
ElevenLabsClient.EnableDebug = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace ElevenLabs.Tests
{
internal class Test_Fixture_000_Proxy : AbstractTestFixture
internal class TestFixture_000_Proxy : AbstractTestFixture
{
[Test]
public async Task Test_01_Health()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@

namespace ElevenLabs.Tests
{
internal class Test_Fixture_00_Authentication
internal class TestFixture_00_Authentication
{
[SetUp]
public void Setup()
{
var authJson = new AuthInfo("key-test12");
var authText = JsonSerializer.Serialize(authJson);
File.WriteAllText(".elevenlabs", authText);
File.WriteAllText(ElevenLabsAuthentication.CONFIG_FILE, authText);
}

[Test]
public void Test_01_GetAuthFromEnv()
public void Test_01_GetAuthFromEnvironment()
{
var auth = ElevenLabsAuthentication.LoadFromEnv();
var auth = ElevenLabsAuthentication.LoadFromEnvironment();
Assert.IsNotNull(auth);
Assert.IsNotNull(auth.ApiKey);
Assert.IsNotEmpty(auth.ApiKey);
}

[Test]
public void Test_02_GetAuthFromFile()
public void Test_02_GetAuthFromPath()
{
var auth = ElevenLabsAuthentication.LoadFromDirectory();
var auth = ElevenLabsAuthentication.LoadFromPath(ElevenLabsAuthentication.CONFIG_FILE);
Assert.IsNotNull(auth);
Assert.IsNotNull(auth.ApiKey);
Assert.AreEqual("key-test12", auth.ApiKey);
Expand Down Expand Up @@ -119,9 +119,9 @@ public void Test_09_CustomDomainConfigurationSettings()
[TearDown]
public void TearDown()
{
if (File.Exists(".elevenlabs"))
if (File.Exists(ElevenLabsAuthentication.CONFIG_FILE))
{
File.Delete(".elevenlabs");
File.Delete(ElevenLabsAuthentication.CONFIG_FILE);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace ElevenLabs.Tests
{
internal class Test_Fixture_01_UserEndpoint : AbstractTestFixture
internal class TestFixture_01_UserEndpoint : AbstractTestFixture
{
[Test]
public async Task Test_01_GetUserInfo()
Expand Down
Loading

0 comments on commit 06f49fe

Please sign in to comment.