API Gateway configuration files

API Gateway configuration files are located in the installation location, by default %ProgramFiles%\Milestone\XProtect API Gateway\.

These configuration files are relevant for the API Gateway:

  • appsettings.json: Reverse proxy (routing), CORS, WebRTC, log levels, etc.

  • appsettings.Production.json: Overrides the configuration settings in appsettings.json.

  • nlog.config: Log layout, log targets, etc.

Editing configuration files

Use a validating editor to edit configuration files. Most popular code editors support JSON and XML syntax validation, either by default or through extensions.

appsettings.json and appsettings.Production.json

Do not edit appsettings.json manually. This file is created by the product installer and maintained by the Server Configurator.

If you need to override a configuration setting in appsettings.json, create appsettings.Production.json and add configuration overrides here. appsettings.Production.json will not be removed or changed by product updates.

To override configuration settings in appsettings.json, copy the complete top level property from appsettings.json to appsettings.Production.json and remove the nested properties that you don't want to change.

For example, to change the management server host address but no other ReverseProxy settings, include this in appsettings.Production.json:

{
  "ReverseProxy": {
    "Clusters": {
      "managementserver": {
        "Destinations": {
          "hostname": {
            "Address": "https://test-02.example.com/"
          }
        }
      }
    }
  }
}

If you add several properties to appsettings.Production.json, remember to include a comma between the properties, but no trailing comma:

{
  "Logging": {
    "LogLevel": {
      "Yarp": "Information"
    }
  },
  "ReverseProxy": {
    "Clusters": {
      "managementserver": {
        "Destinations": {
          "hostname": {
            "Address": "https://test-02.example.com/"
          }
        }
      }
    }
  }
}

Reverse proxy

The reverse proxy (routing) functionality of the API Gateway is implemented using YARP.

This part of appsettings.json is related to the reverse proxy functionality. The configuration is created by the product installer and maintained by the Server Configurator.

  "ReverseProxy": {
    "Routes": {
      "well-known": {
        "ClusterId": "managementserver",
        "Match": {
          "Path": "/.well-known/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/ManagementServer/.well-known/{**remainder}"
          }
        ]
      },
      "rest-api": {
        "ClusterId": "managementserver",
        "Match": {
          "Path": "/rest/v1/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/ManagementServer/Rest/{**remainder}"
          }
        ]
      },
      "alarm-definitions-rest-api": {
        "ClusterId": "managementserver",
        "Match": {
          "Path": "/rest/v1/alarmDefinitions/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/ManagementServer/Rest/alarmDefinitions/{**remainder}"
          }
        ]
      },
      "events-rest-api": {
        "ClusterId": "eventserver",
        "Match": {
          "Path": "/rest/v1/events/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/rest/events/v1/events/{**remainder}"
          }
        ]
      },
      "alarms-rest-api": {
        "ClusterId": "eventserver",
        "Match": {
          "Path": "/rest/v1/{resource:regex(^alarm.*)}/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/rest/alarms/v1/{resource}/{**remainder}"
          }
        ]
      },
      "ws-messages": {
        "ClusterId": "eventserver",
        "Match": {
          "Path": "/ws/messages/v1/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/ws/messages/v1/{**remainder}"
          }
        ]
      },
      "ws-events": {
        "ClusterId": "eventserver",
        "Match": {
          "Path": "/ws/events/v1/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/ws/events/v1/{**remainder}"
          }
        ]
      },
      "idp": {
        "ClusterId": "managementserver",
        "Match": {
          "Path": "/IDP/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/IDP/{**remainder}"
          }
        ]
      },
      "share": {
        "ClusterId": "managementserver",
        "Match": {
          "Path": "/share/{**remainder}"
        },
        "Transforms": [
          {
            "PathPattern": "/share/{**remainder}"
          },
          {
            "X-Forwarded": "Append",
            "Prefix": "Off"
          },
          {
            "RequestHeader": "X-Forwarded-Prefix",
            "Append": "/api/share"
          }
        ]
      }
    },
    "Clusters": {
      "managementserver": {
        "Destinations": {
          "hostname": {
            "Address": "https://test-02.example.com/"
          }
        }
      }
    }
  }

For more information about YARP, please refer to YARP: Yet Another Reverse Proxy. 1

Cross-Origin Resource Sharing (CORS)

The API Gateway can be configured to support Cross-Origin Resource Sharing (CORS). The following response headers are supported:

CORS is disabled by default. You enable and configure CORS support by creating and editing appsettings.Production.json.

  1. Create appsettings.Production.json (if not already created).

  2. Enable and configure CORS response headers similar to this:

    {
      "CORS": {
        "Enabled": true,
        "Access-Control-Allow-Origin": "yourdomain1.com,yourdomain2.com",
        "Access-Control-Allow-Headers": "Content-Type",
        "Access-Control-Allow-Methods": "*"
      }
    }
  3. Restart the IIS, or at least recycle VideoOS ApiGateway AppPool.

Only required response headers should be defined. Each response header can have multiple values, provided as a list of comma-separated values.

In a production system, always specify the Access-Control-Allow-Origin value with explicit origins. Never use wildcard (*) or null in your origin as this can put the security of your system at risk.

For development and test purposes, you can use a very permissive policy:

{
  "CORS": {
    "Enabled": true,
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Headers": "*",
    "Access-Control-Allow-Methods": "*"
  }
}

This will allow calls from any origin, including a local file system, to the API Gateway.

For more information about CORS, please refer to Cross-Origin Resource Sharing (CORS)5.

WebRTC

WebRTC is a peer-to-peer protocol for streaming data, for example video.

STUN and TURN server addresses

To help establish a connection through NATs, WebRTC uses STUN (Session Traversal Utilities for NAT) and/or TURN (Traversal Using Relays around NAT) servers.

A STUN server is used to discover the public IP address and port number of a device behind a NAT.

A TURN server is used to relay traffic between peers when a direct connection is not possible due to firewall or NAT restrictions. TURN servers can also act as STUN servers.

No default STUN or TURN server URLs are configured API Gateway-side.

To specify STUN and/or TURN servers:

  1. Create appsettings.Production.json (if not already created).

  2. Add a WebRTC object and add STUN and TURN server URLs, for example:

    {
      "WebRTC": {
        "iceServers": [
          { "url": "stun:mystun.zyx:3478" },
          { "url": "turn:mystun.zyx:5349" },
        ]
      }
    }
  3. Restart the IIS, or at least recycle VideoOS ApiGateway AppPool.

For more information about WebRTC, please refer to WebRTC API6 and the WebRTC sample documentation at https://github.com/milestonesys/mipsdk-samples-protocol/tree/main/WebRTC_JavaScript.

Logging

The API Gateway uses NLog for logging.

Logging is configured in two places:

  • appsettings.json and appsettings.Production.json: Log levels

  • nlog.config: Log layout, log targets, etc.

Log levels

This part of appsettings.json is related to logging:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Yarp": "Warning"
    }
  }
}

To include YARP routing log messages, add a log level setting in appsettings.Production.json for Yarp, for example, Information:

  1. Create appsettings.Production.json (if not already created).

  2. Add the configuration that you want to override, for example:

    {
      "Logging": {
        "LogLevel": {
          "Yarp": "Information"
        }
      }
    }
  3. Restart the IIS, or at least recycle VideoOS ApiGateway AppPool.

Log layout, log targets, etc

This is the default NLog configuration file nlog.config:

<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  autoReload="true"
  internalLogLevel="Warn"
  internalLogFile="internal-nlog.txt">
  <variable
    name="logDirectory"
     value="C:\ProgramData\Milestone\ApiGateway\Logs" />
  <variable
    name="archiveDirectory"
   value="${var:logDirectory}\Archive" />
  <variable
    name="defaultLayout" 
    value="${date:format=yyyy-MM-dd HH\:mm\:ss.fffzzz} [${threadid:padding=6}] ${level:uppercase=true:padding=-10} - ${message} ${exception:format=tostring}" />
  <targets>
    <target
      name="logfile"
      xsi:type="File"
      fileName="${var:logDirectory}\gateway.log"
      archiveFileName="${var:archiveDirectory}\gateway-{####}.log"
      archiveNumbering="Rolling"
      maxArchiveFiles="20"
      archiveEvery="Day"
      archiveAboveSize="1000000"
      archiveOldFileOnStartup="true"
      createDirs="true"
      layout="${var:defaultLayout}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
  </rules>
</nlog>

With the configuration setting autoReload="true", NLog will monitor and reload the configuration file whenever it is modified. You can change the log configuration on the fly without restarting anything.

For more information about NLog configuration, please refer to NLog Configuration options.7