@sinequa/atomic

Developing against a remote server

Why a cross-origin backendUrl fails in development, and the proxy configuration that fixes it — for Vite and for Angular.

The examples in this documentation set backendUrl to the Sinequa server. That works when your application is served from that server, and it is the deployed case. In development it usually is not: your application runs on localhost and the server is somewhere else — and then it fails.

The fix is a development proxy, and it is not optional.

Why not just configure CORS

Because the session is a cookie, and cookies are harder than headers.

cross-origin request no yes third-party,SameSite yes localhost:4200 search.example.com CORS allowsthe origin? blocked by the browser cookie accepted? request goes through,no session works

Two obstacles, and CORS only removes the first:

  • CORS. The server must name your origin explicitly. With credentials in play, Access-Control-Allow-Origin: * is rejected by the browser — a wildcard and cookies are mutually exclusive.
  • The cookie itself. From localhost to another origin, the session cookie is a third-party cookie. Current browsers restrict those by default, so the requests can succeed while carrying no session at all — which surfaces as a login form that reappears after every successful sign-in.

A proxy sidesteps both: the browser only ever talks to your own origin, so nothing is cross-origin and nothing is third-party.

With a proxy, omit backendUrl

Leave it out and the library builds relative URLs, which the dev server then forwards. Setting it to the remote server defeats the proxy — the browser goes straight there, cross-origin, and you are back to both problems.

What has to be proxied

Not just /api. A search interface reaches the server through several paths, and the ones that are easy to forget are precisely the ones whose failure is hard to read.

PathWhy
/apiEvery call the library makes
/assetsStylesheets and images a document preview's cached rendition references
/xdownloadDocument downloads and query exports
/auth/redirect, /saml/redirectWhere an identity provider returns after an OAuth or SAML sign-in
/rServer-side redirection links
/endpointsServer-declared endpoints

Miss /assets and previews render unstyled. Miss the redirect paths and a provider sign-in never comes back — the loop guard fires and reports that the callback is not authorised for this application, which is technically true and thoroughly misleading.

The configuration

Where these come from

The Angular configuration below is one taken from a working deployment — the path list in particular is what practice settled on, not what a specification says. The Vite variant applies that same list, but it has not been proven the same way: treat it as a starting point, and add whatever your own deployment turns out to reach.

A development proxy for a remote Sinequa server
vite.config.ts
import basicSsl from "@vitejs/plugin-basic-ssl";
import { defineConfig } from "vite";

/** Everything a search interface reaches on the server, not only /api. */
const PROXIED = ["/api", "/assets", "/xdownload", "/auth/redirect", "/saml/redirect", "/r", "/endpoints"];

const target = "https://<your-sinequa-server>";

export default defineConfig({
  // HTTPS is required, not a precaution: the session cookie is `Secure`, so it is
  // only kept on an https origin. Unlike the Angular CLI, Vite generates no
  // certificate — this plugin does. `npm i -D @vitejs/plugin-basic-ssl`
  plugins: [basicSsl()],

  server: {
    proxy: Object.fromEntries(
      PROXIED.map((path) => [
        path,
        {
          target,
          changeOrigin: true,
          // `false` only for a server with a self-signed certificate.
          secure: true,
          ws: true,
        },
      ]),
    ),
  },
});

Then run the dev server as usual — ng serve, vite — and the application talks only to localhost.

HTTPS is required on both sides

Not only the target: your own dev server has to serve HTTPS. The session cookie is Secure, so it is dropped on an http:// origin — the requests then succeed while the session silently fails to stick, which looks exactly like a broken sign-in.

The Angular CLI generates the certificate for you with ssl: true. Vite does not, which is why the configuration above adds @vitejs/plugin-basic-ssl. Your browser asks you to accept the certificate once, on first load.

The one build that works everywhere

Omitting backendUrl is not a development-only trick. In production the application is served by the Sinequa server, so relative URLs are already correct. The same build therefore works in both places, and there is no environment switch to get wrong.

Keep backendUrl for the cases that genuinely need it: a second backend on one page, a headless consumer with no origin of its own, or a deployment where CORS is properly configured and the cookie is not an obstacle.

Pitfalls

What's next

On this page