Table of Contents

Deploying under a custom base path (PathBase)

Products: FastReport Corporate Server, FastReport Publisher

By default, FastReport Corporate Server or Publisher occupies the root of your domain (https://company.com/...). If you already run other services on the same domain (or want to share a single cookie session with them), you can deploy the product under a custom URL prefix.

Example: with the prefix /reports the product becomes available at URLs like https://company.com/reports/api/..., https://company.com/reports/app/, https://company.com/reports/designer/..., and so on.

1. What this gives you

  • The whole product is served under the prefix — the web app, the public API, the Online Designer, and the static/WASM previews.
  • A single sign-in works across all of them: the authentication cookie covers the whole domain, so you stay signed in when moving between /reports/app/, /reports/designer/, /reports/api/..., etc.
  • The Backend's API documentation (Swagger / OpenAPI) exposes the prefixed paths.

2. Configuration

2.1. appsettings.json

Set MainConfig.Server.PublicPathBase to the prefix you want. Empty by default (root hosting).

{
  "MainConfig": {
    "Server": {
      "PublicPathBase": "/reports"
    }
  }
}

The setup wizard asks for this value on its configuration screen ("Public base path") and writes it into the generated appsettings.Production.json, which is mounted into every service container.

2.2. Environment variables

Use the standard ASP.NET Core override mechanism (double underscore __ for nested keys):

MainConfig__Server__PublicPathBase=/reports

The variable must be present in the environment of each service container — a value exported in the host shell does not reach Docker containers or Kubernetes pods. In Docker Compose add an environment: entry to each service; in Kubernetes add env: to each container. For the shipped installs this is unnecessary — the shared appsettings.Production.json (section 2.1) is mounted into every container already.

The public prefix stays in the request path end to end: the proxy forwards /reports/... unchanged, and every service (the Gateway included) moves the prefix onto Request.PathBase itself via UsePathBase — so framework-generated URLs (redirects, Location, Swagger) carry the prefix automatically. No per-service tuning is needed.

3. Example nginx deployment

server {
    listen 443 ssl;
    server_name company.com;

    ssl_certificate     /etc/ssl/certs/company.com.crt;
    ssl_certificate_key /etc/ssl/private/company.com.key;

    # Forward /reports/ requests to the Gateway, passing the full URI unchanged.
    # Do NOT add a trailing slash to proxy_pass — `http://gateway/` would strip the
    # /reports prefix and the services would never see it: the prefix must stay in
    # the request path; every service strips it itself via UsePathBase.
    location /reports/ {
        proxy_pass http://gateway;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_http_version 1.1;
        proxy_set_header Connection        "";
        proxy_buffering off;
    }
}

4. Example Kubernetes deployment (Ingress)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gateway
spec:
  tls:
    - hosts: [company.com]
      secretName: company-com-tls
  rules:
    - host: company.com
      http:
        paths:
          - path: /reports(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: fr-gateway
                port:
                  number: 80
  • Auth cookie is set with Path=/ on the whole domain, so it is sent for /reports/app/, /reports/designer/, /reports/api/... and the rest without re-authentication.
  • OIDC callback — your identity provider (e.g. https://id.fast-report.com) will receive a redirect_uri like https://company.com/reports/account/oidc/signin-*. Register that URL in your IdP client config with the prefix.

6. Known limitations

  • LogoLink / FaviconLink / HomePageLink / AboutLink / SlaLink / FirstStepsVideoLink in MainConfig.Server must include the prefix when they use relative paths (e.g. /assets/logo.svg → /reports/assets/logo.svg). For absolute URLs, include the prefix in the host.
  • Do not use a prefix that contains a service segment name — app, admin, designer, wasmpreview, or staticpreview (e.g. /app/reports or /reports/admin/...). Such a prefix is not supported and the app will not resolve correctly under it.

7. Minimal working example

The entire configuration needed is a single key in the shared MainConfig (appsettings.json):

{
  "MainConfig": {
    "Server": {
      "PublicPathBase": "/reports"
    }
  }
}

Put the services behind a reverse proxy that forwards /reports/ to the Gateway (see section 3 for nginx, section 4 for a Kubernetes Ingress). Every service strips the prefix itself once the value reaches its configuration — in the shipped installs the shared appsettings.Production.json is mounted into every container, so this one value is all it takes — and the application loads under the /reports prefix (e.g. https://company.com/reports/app/).

8. Using the SDK with a path-base deployment

A client that consumes the public API through the FastReport Cloud SDK must send every request under the public prefix. The mechanism differs between the C# and JavaScript SDKs, and the C# one has a sharp edge.

C# SDK (FastReport.Cloud.SDK / FastReport.Cloud.SDK.Web)

There is no PathBase/basePath option — the prefix must be part of the base URL, and that base URL must end with a trailing slash. .NET resolves the SDK's relative request URIs (api/manage/v1/...) against the base URL per RFC 3986, replacing its last path segment, so without the trailing slash the prefix segment is silently dropped.

// CORRECT — requests go to https://company.com/reports/api/manage/v1/...
services.AddFastReportCloud(options =>
{
    options.Host = "https://company.com/reports/"; // prefix + trailing slash
    options.ApiKey = "...";
});

// or, when you construct the HttpClient yourself:
httpClient.BaseAddress = new Uri("https://company.com/reports/");
// WRONG — .NET resolves "api/manage/v1/ApiKeys" against "https://company.com/reports"
// and DROPS "/reports": requests silently hit the domain root (404 / wrong tenant).
options.Host = "https://company.com/reports"; // no trailing slash

JavaScript SDK (fastreport-cloud-sdk)

The JS SDK exposes a configurable basePath and builds URLs by string concatenation rather than RFC 3986 resolution, so a trailing slash is not required — the constructor strips it:

const apiClient = new ApiClient();
apiClient.basePath = "https://company.com/reports"; // trailing slash optional