Skip to main content

Overview

ISAPI (Internet Server Application Programming Interface) deployment allows you to run Horse applications as native IIS extensions. This provides deep integration with Microsoft’s web server infrastructure, including IIS’s process management, security, and performance features.
ISAPI deployment is Windows-only and requires the HORSE_ISAPI conditional define. The project must be compiled as a DLL library.

When to Use ISAPI Deployment

  • Windows Server Environments: Native IIS integration on Windows Server
  • Enterprise Applications: Leverage existing IIS infrastructure and management
  • ASP.NET Integration: Run alongside ASP.NET applications
  • Windows Authentication: Use integrated Windows authentication
  • High Performance: Direct integration with IIS worker processes
  • Shared Hosting: Multiple applications on single IIS instance

Required Conditional Define

You must add HORSE_ISAPI to your project’s conditional defines and compile as a library.
1

Open Project Options

Go to Project → Options → Delphi Compiler → Compiling
2

Add Conditional Define

In the “Conditional defines” field, add: HORSE_ISAPI
3

Change Project Type to Library

Ensure your project starts with library (not program)
4

Rebuild Project

Clean and rebuild your project completely

Complete ISAPI Example

library ISAPI;

{$R *.res}

uses Horse;

begin
  // Need to set "HORSE_ISAPI" compilation directive

  THorse.Get('/ping',
    procedure(Req: THorseRequest; Res: THorseResponse)
    begin
      Res.Send('pong');
    end);

  THorse.Listen;
end.

Advanced ISAPI Application

library MyISAPIApp;

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  System.JSON,
  Horse,
  Horse.Jhonson, // JSON middleware
  Horse.CORS;     // CORS support

begin
  // Enable CORS for cross-origin requests
  THorse.Use(CORS);
  
  // Enable JSON parsing
  THorse.Use(Jhonson);

  // Health check endpoint
  THorse.Get('/health',
    procedure(Req: THorseRequest; Res: THorseResponse)
    begin
      Res.Send('{"status": "healthy", "server": "IIS/ISAPI"}');
    end);

  // API endpoints
  THorse.Get('/api/users',
    procedure(Req: THorseRequest; Res: THorseResponse)
    var
      Users: TJSONArray;
      User: TJSONObject;
    begin
      Users := TJSONArray.Create;
      try
        User := TJSONObject.Create;
        User.AddPair('id', '1');
        User.AddPair('name', 'John Doe');
        Users.AddElement(User);
        
        User := TJSONObject.Create;
        User.AddPair('id', '2');
        User.AddPair('name', 'Jane Smith');
        Users.AddElement(User);
        
        Res.Send<TJSONArray>(Users);
      finally
        Users.Free;
      end;
    end);

  THorse.Get('/api/users/:id',
    procedure(Req: THorseRequest; Res: THorseResponse)
    var
      UserId: string;
      User: TJSONObject;
    begin
      UserId := Req.Params['id'];
      
      User := TJSONObject.Create;
      try
        User.AddPair('id', UserId);
        User.AddPair('name', 'User ' + UserId);
        User.AddPair('email', Format('user%[email protected]', [UserId]));
        
        Res.Send<TJSONObject>(User);
      finally
        User.Free;
      end;
    end);

  THorse.Post('/api/users',
    procedure(Req: THorseRequest; Res: THorseResponse)
    var
      Body: TJSONObject;
      Response: TJSONObject;
    begin
      Body := Req.Body<TJSONObject>;
      
      Response := TJSONObject.Create;
      try
        Response.AddPair('id', '3');
        Response.AddPair('name', Body.GetValue('name').Value);
        Response.AddPair('created', 'true');
        
        Res.Status(201).Send<TJSONObject>(Response);
      finally
        Response.Free;
      end;
    end);

  // Error handling
  THorse.Get('/api/error',
    procedure(Req: THorseRequest; Res: THorseResponse)
    begin
      raise Exception.Create('Test error');
    end);

  THorse.Listen;
end.

IIS Configuration

Step-by-Step Setup

1

Enable ISAPI Extensions

Open Server ManagerManageAdd Roles and FeaturesNavigate to: Web Server (IIS)Web ServerApplication DevelopmentCheck:
  • ✅ ISAPI Extensions
  • ✅ ISAPI Filters
2

Copy DLL to Web Directory

Copy your compiled ISAPI.dll to your IIS website directory:
copy ISAPI.dll "C:\inetpub\wwwroot\api\"
3

Configure ISAPI Restrictions

Open IIS Manager → Select Server → ISAPI and CGI RestrictionsClick Add and configure:
  • Path: C:\inetpub\wwwroot\api\ISAPI.dll
  • Description: Horse API
  • ✅ Allow extension path to execute
4

Create Application or Virtual Directory

Right-click on your website → Add Application or Add Virtual DirectoryConfigure:
  • Alias: api
  • Physical path: C:\inetpub\wwwroot\api
  • Application pool: Select or create pool
5

Add Handler Mapping

Select your application → Handler MappingsAdd Script MapConfigure:
  • Request path: *
  • Executable: C:\inetpub\wwwroot\api\ISAPI.dll
  • Name: Horse_ISAPI
6

Test the Application

Navigate to: http://localhost/api/ping

Web.config Configuration

Create a web.config file in your application directory:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="Horse_ISAPI" 
           path="*" 
           verb="*" 
           modules="IsapiModule" 
           scriptProcessor="C:\inetpub\wwwroot\api\ISAPI.dll" 
           resourceType="Unspecified" 
           requireAccess="Execute" 
           preCondition="bitness64" />
    </handlers>
    
    <!-- Enable detailed errors for debugging -->
    <httpErrors errorMode="Detailed" />
    
    <!-- Increase request limits if needed -->
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="52428800" />
      </requestFiltering>
    </security>
    
    <!-- Default document -->
    <defaultDocument enabled="false" />
    
    <!-- URL Rewrite (if module installed) -->
    <rewrite>
      <rules>
        <rule name="Horse API" stopProcessing="true">
          <match url="^api/(.*)" />
          <action type="Rewrite" url="ISAPI.dll/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Application Pool Configuration

1

Create Dedicated Application Pool

Open IIS ManagerApplication PoolsAdd Application PoolConfigure:
  • Name: HorseAPI
  • .NET CLR version: No Managed Code
  • Managed pipeline mode: Integrated
2

Configure Advanced Settings

Right-click pool → Advanced SettingsKey settings:
General:
  .NET CLR Version: No Managed Code
  Enable 32-Bit Applications: False (for 64-bit DLL)

Process Model:
  Identity: ApplicationPoolIdentity
  Idle Time-out: 20 minutes
  Maximum Worker Processes: 1 (or more for web garden)

Recycling:
  Regular Time Interval: 1740 (29 hours)
  Generate Recycle Event Log Entry: True
3

Set Application Pool

Select your application → Basic Settings → Choose your pool

Security Configuration

Authentication

<configuration>
  <system.webServer>
    <security>
      <authentication>
        <!-- Anonymous authentication -->
        <anonymousAuthentication enabled="true" />
        
        <!-- Windows authentication -->
        <windowsAuthentication enabled="false" />
        
        <!-- Basic authentication -->
        <basicAuthentication enabled="false" />
      </authentication>
    </security>
  </system.webServer>
</configuration>

SSL/TLS Configuration

For ISAPI applications, SSL is typically configured at the IIS level, not in the application code.
1

Install SSL Certificate

IIS Manager → Server → Server CertificatesImport or Create Self-Signed Certificate
2

Add HTTPS Binding

Select your site → BindingsAddConfigure:
  • Type: https
  • Port: 443
  • SSL certificate: Select your certificate
3

Require SSL (Optional)

Select your application → SSL SettingsConfigure:
  • ✅ Require SSL
  • Client certificates: Accept or Ignore

Force HTTPS Redirect

<configuration>
  <system.webServer>
    <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:1}" 
                  redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Debugging

Enable Detailed Errors

<configuration>
  <system.webServer>
    <httpErrors errorMode="Detailed" />
  </system.webServer>
  <system.web>
    <customErrors mode="Off" />
  </system.web>
</configuration>

Failed Request Tracing

1

Enable Tracing

IIS Manager → Site → Failed Request TracingEnable
2

Add Tracing Rule

Failed Request Tracing RulesAddConfigure to trace:
  • All content (*)
  • Status codes: 400-999
  • Time taken > 30 seconds

Performance Optimization

Output Caching

<configuration>
  <system.webServer>
    <caching>
      <profiles>
        <add extension=".dll" 
             policy="DontCache" 
             kernelCachePolicy="DontCache" />
      </profiles>
    </caching>
  </system.webServer>
</configuration>

Compression

<configuration>
  <system.webServer>
    <httpCompression>
      <dynamicTypes>
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/xml" enabled="true" />
      </dynamicTypes>
    </httpCompression>
  </system.webServer>
</configuration>

Troubleshooting

Common Issues

HTTP Error 500.0 - Internal Server Error
  • Missing HORSE_ISAPI conditional define
  • DLL compiled for wrong architecture (32/64-bit)
  • Missing dependencies or runtime packages
HTTP Error 404.2 - ISAPI and CGI Restrictions
  • ISAPI extension not allowed in IIS
  • Add DLL to ISAPI restrictions list
Handler Mapping Error
  • Incorrect path to DLL in handler mapping
  • Check file permissions on DLL

Check Event Logs

# View IIS logs
Get-EventLog -LogName Application -Source "IIS*" -Newest 20

# View System logs
Get-EventLog -LogName System -Source "IIS*" -Newest 20

Test DLL Registration

# Register ISAPI DLL manually (rarely needed)
regsvr32 "C:\inetpub\wwwroot\api\ISAPI.dll"

# Check file permissions
icacls "C:\inetpub\wwwroot\api\ISAPI.dll"

Deployment Checklist

1

Build Configuration

HORSE_ISAPI conditional define set
✅ Compiled as library (not program)
✅ Release configuration
✅ Correct architecture (32/64-bit)
✅ All dependencies included
2

IIS Configuration

✅ ISAPI Extensions enabled
✅ DLL in ISAPI restrictions
✅ Handler mapping configured
✅ Application pool created
✅ Permissions set correctly
3

Testing

✅ Health check endpoint responds
✅ API endpoints working
✅ Error handling functions
✅ SSL/HTTPS working (if configured)

Next Steps

Apache Module

Deploy with Apache HTTP Server

CGI Deployment

Standard CGI deployment option

Build docs developers (and LLMs) love