🌈

Websocket

In modern web applications, WebSocket has become a popular technology for real-time communication. It enables data exchange between clients and servers over a single TCP connection. It is part of HTML5 and is widely supported by modern web browsers, including Chrome, Firefox, Safari, and Edge.

WebSocket connection failure is a common issue in web development.

https://apidog.com/blog/websocket-connection-failed

Ville bare resolve en feil som kommer i browser Console ved navigering som treffer nginx. Viser seg at nginx-configs må tilpasses med følgende direktiver for å slippe til Websocket connection:

    location / {
        ...
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
    }

Fetching av tenant data

ChatGPT hadde ikke godt svar her, og post på Payload-discord er ikke besvart:

I’m making a PoC with Payload as multi-tenant CMS for some Next frontends. My query for tenant-specific data returns an empty list, and so I’d just like to check that my thinking and setup is correct.

I’m on localhost with my Payload backend (clone of multi-tenant example) and two Next frontends running on each their own port:

  • – The collection I’m querying is set up with a tenant field. I can logon as tenant admin and see other tenants’ data filtered out.
  • – My tenants are set up with a slug field, and their domains field is set up with a test domain that is mocked in Windows hosts file. I’m querying the data like so: http://tenant-mock.localhost/cms/api/courses?where[tenant][slug][equals]=tenant-slug
  • – I have Payload config set up with routes { api: "/cms/api" } to let the Next apps use that route. Then I have nginx configured for each host domain to redirect / to the Next frontend and /admin and /cms to my Payload backend.

Hjalp ikke å sette access: { read: () => true } på collection heller; det sto tenants der før som ville ført til tom liste i seg selv.

Hjalp ikke å fikse Websocket-feilen, forventet ikke egentlig at den spilte inn.

Hjalp ikke å sette cors: [ "*" ] i Payload config.

Sitter med denne på andre dagen og føler at det er en dum feil.

EDIT: La til depth=2 i querystringen og da får jeg data. Men får alt, ikke bare tilhørende tenanten (som også står i querystringen). Er rart for jeg trodde nettopp depth gjorde det mulig å nå tenant-feltet.

EDIT 2: Løsningen var å autorisere requesten til å representere en tenant-admin, da blir andre tenants filtert bort automagisk.

Det er to måter å gjøre det på: Autorisering som user, og autorisering med API-nøkkel tilknyttet en user. Det var mulig å sette config auth: { useAPIKey: true } på User-collection, i adminpanelet ble det da mulig å hake av for om API-nøkkel skal brukes for hver enkelt bruker. Da kan man opprette API-nøkkel på alle tenant-admins, og la hver frontend querye backenden som om de var tenant-admins, med API-nøkkelen.

Å gjøre access: read tilgjengelig overalt førte bare til at alle tenants’ data ble returnert. Uten autorisering klarte ikke Payload å skille mellom tenant-data, antagelig fordi den bruker tilgangskontrollen til å skille mellom dataene.

Filteret med queryparams fikk jeg aldri til å fungere, verken med REST eller graphQL.

depth hadde ikke noe å si til slutt; straks queryen funket kunne jeg fjerne dette parameteret.

👻

Fant ut hvorfor tenant admin ikke ble autorisert for admin-dashboardet ved login. Den må navigere inn fra domenet til tenanten den er admin for. Det er fordi Payload leser av domenet og matcher den mot tenant-domenene til useren. Så useren blir autentisert, men ikke autorisert hvis den logger seg inn fra et domene den ikke administrerer.

Custom /api route for Payload

Man kan definere custom routes i Payloads config:

  routes: {
    api: "/cms/api"
  }

Nginx config måtte endres fra /api til:

location /cms {
    proxy_pass http://localhost:3000; # Your CMS app port
    ...
}

Next-appene får da /api-routen for seg selv.

Hosts-fila

Hosts-fila (ligger i C:\Windows\System32\drivers\etc på Windows) er en statisk fil der man kan legge inn custom mappinger fra domenenavn til IP-adresser. Ved HTTP requests sjekker operativsystemet hosts-fila før den eventuelt gjør en ekstern DNS-lookup.

Jeg bruker den til å mappe test-domener til 127.0.0.1 for å mocke produksjon, der forskjellige domener blir å route inn utenfra. Testdomenene representerer tenants som jeg kan jobbe med lokalt. Da kan jeg navigere til dem i browseren, og hosts-fila mapper meg til localhost:

# First Bird tenants
127.0.0.1 hjertets-tempel.localhost
127.0.0.1 oscar-floor.localhost

Navigering uten port, eller til kun localhost får refusal to connect i browseren, antagelig fordi det er ambiguøst. Det er to Next-apper jeg har kjørende, en på port 3001 og en på port 3002. De kan jeg nå på hjertets-tempel.localhost:3001 respektivt oscar-floor.localhost:3002.

Det funker også å bruke nginx til å revers-proxye fra hostnavn til riktig port. I tillegg bruker jeg nginx til å revers-proxye hvert domene til backend eller frontend basert på route:

  • Alle apper har felles backend på route testdomene.localhost/admin og /api (port 3000)
  • Hver app har egen frontend på route testdomene.localhost/ (egen port)

⚠️ Det viste seg at ved navigering til /admin gjør backenden kall til endepunkter under /api, der jeg får 404 hvis ikke også disse kallene blir revers-proxyet til 3000-porten. Det er litt dumt, for frontendene har også kall de trenger å gjøre til endepunkter under samme route, /api.

ChatGPT foreslår å endre en eller alle routene for å separere dem skikkelig, i så fall gir det mening å skille ut kun backend-routen så ikke den går i beina på noen av frontendene. Jeg vet ikke hvordan man får til det uten å endre i kildekoden til Payload.

Forresten – det blir ikke et problem hvis jeg hoster backenden på et annet sted enn frontendene. Tanken er å hoste backenden i Payload Cloud. Da får man en del features på kjøpet, typ epost. Det er sikkert mulig å hoste frontendene sammen med den, og sikkert billigere.