Net-Base Tímarit

09.06.2026

REST API með RemObjects SDK: hreint útgáfustjórnun og bilanaleit á JSON-endapunktum (Delphi kóðasneið)

Hvernig á að byggja REST API með RemObjects SDK í Delphi sem brotnar ekki í rekstri: stöðugir JSON-samningar, útgáfustjórnun án URL-óreiðu, Correlation-ID í gegnum öll lög, miðlægt villukort, snapshot-logging fyrir erfiða villuleit og hagnýtar ábendingar...

09.06.2026

Frá tímaritsþema til verkefnaframkvæmdar

Viðeigandi þjónustu- og tæknisíður fyrir greinina

Af hverju „REST API mit RemObjects SDK“ ræðst oft á jaðarsvæðum í framkvæmd

Ein REST API mit RemObjects SDK stendur sjaldan og fellur við „Hello World“-þjóninn, heldur við þær aðstæður þar sem rekstur, eldri kerfi og innleiðing mætast: útgáfustjórnun án stöðvunar, samkvæmur villuháttur yfir alla endapunkta, endurtekjanleg villuleit í gegnum proxy-keðjur og hæfni til að tengja beiðnir óyggjandi í vandamálatilfellum.

RemObjects SDK kemur með mikið af innviðum fyrir þetta: þjónustur, skilaboðaform, serialisierung, hýsingu (t.d. sem Windows- und Linux-Services eða aftan við IIS/Reverse Proxy) og skilgreindar staðsetningar til að meðhöndla villur miðlægt. Það sem hins vegar oft vantar í vaxandi fyrirtækjahugbúnaðarumhverfum er einhleypur, konsekvent framfylgdur samningur: Hvaða JSON-Felder eru stöðug? Hvernig merkjum við villur? Hvernig þekkjum við beiðni aftur þegar hún hefur farið í gegnum Load Balancer, TLS-Termination og margar bakendanámskeið?

Fyrirliggjandi nálgun (inklusive Delphi-Snipsel) sýnir traustan feril fyrir RemObjects SDK: JSON-Verträge versionieren, krefjast Correlation-ID (Request-ID til rekjanleika), þýða Exceptions in HTTP-Status und JSON-Fehlerobjekte og samstilla þannig villuleit og rekstur án þess að láta þau stangast á. Að auki skoðum við jaðartilvik sem koma reglulega upp í raunverulegum umhverfum: þráðavinnslu á þjóninum, gagnagrunns­aðganga með BDE-útskiftingu með innfæddri tengingu, Proxy-Header, Timeouts og „óhreinar“ Client-Payloads.

Arkitektur-Entscheidung: Versionierung über Medien-Typ statt URL

Margar API-útfærslur nota útgáfu í slóðum, til dæmis /v1/. Það er hagnýtt en í langtímainnlimum (t.d. ERP/DMS/CRM-Anbindunge) leiðir það oft til URL-tvítekningar, tvöfaldra leiða, tvöfaldrar prófunar og spurningarinnar „Welche Version nutzen wir eigentlich?“ í rekstrarskýrslum.

Önnur leið er að merkja útgáfu í gegnum Media Type (Content Negotiation). Viðskiptavinurinn sendir t.d. Accept: application/vnd.company.order+json;v=2. Þjónninn les útgáfuna ákvörðunartækt og stillir Contract/DTO-Verhalten í samræmi. Þetta virkar í proxy- og cache-keðjum ef headerar eru framsendir hreint. Fyrir stjórnendur er það einnig vel eftirprufanlegt: beiðni er hægt að endurskapa með Curl/Postman án þess að breyta URLum.

RemObjects SDK er ekki „REST-puristisch“, heldur pragmatiskt Service-Framework. Einmitt þess vegna er miðlategundaraðferðin oft æskileg: þú getur haldið stöðugum endapunktum en þróað samt samninga áfram. Mikilvægt er að þú lesir útgáfuna alltaf, tekur miðlæga ákvörðun á einum stað og færir niðurstöðuna inn í þjónstsamhengið.

Wann kippt die Accept-Header-Variante?

Í framkvæmd eru þrjár algengar brotpunktar sem vert er að taka fyrir fyrirfram:

  • Proxy-Policies: Sumir Reverse Proxies/WAF-reglur normalísera eða sía Accept-Header. Þá fellur API-ið þitt hljóðlega aftur á sjálfgefna útgáfu. Lausn: yfirfara proxy-reglur sérstaklega og, ef þess þarf, nota X-Api-Version sem varamöguleika.
  • Client-Libraries: Nokkrar HTTP-bókasöfn setja eigin Accept-Header og skrifa yfir gildi. Lausn: styðja Contract-Version líka sem valfrjálsan query-parameter (einungis sem fallback), eða lesa Accept-Header á þjóninum á sveigjanlegan hátt.
  • Caching: Ef Response-Caching er í spilinu þarf skyndiminnið að breytast eftir Accept (Vary: Accept), annars mun það skila útgáfu 1 til viðskiptavina sem biðja um útgáfu 2. Lausn: stilla Vary meðvitað eða slökkva á caching á API-stigi.

Kóðasneið: Request-Context, Correlation-ID, Version og Error-Mapping

Kóðinn er meðvitað sniðinn þannig að hann auðvelt sé að samþætta hann í núverandi RemObjects-Serverprojekte: lítil Context-lag, Parser fyrir API-útgáfu (úr Accept), Correlation-ID-kerfi og miðlægur Exception-Mapping. Hugtök:

  • Correlation-ID: Einstakt auðkenni fyrir hverja beiðni sem endurspeglast í svari og er vísað til í loggum.
  • Exception-Mapping: Þýðing innri Delphi-Exceptions í stöðug, viðskiptavinshandhægt villaobjekt (inkl. HTTP-Status).
  • Contract-Version: Útgáfa af JSON-samningi sem stýrir hegðun og reitum.
Delphi
unit Api.Infrastructure;

interface

uses
  System.SysUtils, System.Classes, System.StrUtils, System.Generics.Collections,
  System.JSON;

type
  EApiError = class(Exception)
  private
    FHttpStatus: Integer;
    FCode: string;
    FCorrelationId: string;
  public
    constructor Create(const AHttpStatus: Integer; const ACode, AMessage, ACorrelationId: string);
    property HttpStatus: Integer read FHttpStatus;
    property Code: string read FCode;
    property CorrelationId: string read FCorrelationId;
  end;

  TApiContext = record
    CorrelationId: string;
    ContractVersion: Integer;
    RemoteIp: string;
    UserAgent: string;
    class function New: TApiContext; static;
  end;

  TApiVersion = record
    class function FromAcceptHeader(const AAccept: string; const ADefault: Integer = 1): Integer; static;
  end;

  TApiErrorMapper = class
  public
    class function ToErrorJson(const E: Exception; const ACorrId: string): TJSONObject; static;
    class function ToHttpStatus(const E: Exception): Integer; static;
    class function SafeMessage(const E: Exception): string; static;
  end;

implementation

{ EApiError }

constructor EApiError.Create(const AHttpStatus: Integer; const ACode, AMessage, ACorrelationId: string);
begin
  inherited Create(AMessage);
  FHttpStatus := AHttpStatus;
  FCode := ACode;
  FCorrelationId := ACorrelationId;
end;

{ TApiContext }

class function TApiContext.New: TApiContext;
begin
  Result.CorrelationId := '';
  Result.ContractVersion := 1;
  Result.RemoteIp := '';
  Result.UserAgent := '';
end;

{ TApiVersion }

class function TApiVersion.FromAcceptHeader(const AAccept: string; const ADefault: Integer): Integer;
// Erwartet z.B.: application/vnd.company.order+json;v=2
var
  Parts: TArray<string>;
  P: string;
  V: string;
  I: Integer;
begin
  Result := ADefault;
  if AAccept.Trim.IsEmpty then
    Exit;

  Parts := AAccept.Split([';', ',']);
  for P in Parts do
  begin
    V := Trim(P);
    if StartsText('v=', V) then
    begin
      if TryStrToInt(Copy(V, 3, MaxInt), I) and (I > 0) and (I < 100) then
        Exit(I);
    end;
  end;
end;

{ TApiErrorMapper }

class function TApiErrorMapper.SafeMessage(const E: Exception): string;
// Im Betrieb keine internen Details, keine SQL, keine Pfade.
// Für Debug/Stage kann man das über Konfiguration erweitern.
begin
  if E is EApiError then
    Exit(E.Message);

  if E is EArgumentException then
    Exit('Ungültige Parameter.');

  Exit('Interner Fehler.');
end;

class function TApiErrorMapper.ToHttpStatus(const E: Exception): Integer;
begin
  if E is EApiError then
    Exit(EApiError(E).HttpStatus);

  if E is EArgumentException then
    Exit(400);

  Exit(500);
end;

class function TApiErrorMapper.ToErrorJson(const E: Exception; const ACorrId: string): TJSONObject;
var
  Code: string;
  Status: Integer;
  Msg: string;
begin
  Status := ToHttpStatus(E);
  Msg := SafeMessage(E);

  if E is EApiError then
    Code := EApiError(E).Code
  else if E is EArgumentException then
    Code := 'bad_request'
  else
    Code := 'internal_error';

  Result := TJSONObject.Create;
  Result.AddPair('error', TJSONObject.Create
    .AddPair('code', Code)
    .AddPair('message', Msg)
    .AddPair('httpStatus', TJSONNumber.Create(Status))
    .AddPair('correlationId', ACorrId));
end;

end.

Tilgangur: Stöðugt beiðnasamhengi fremur en „einhvers staðar í Threadlocal“

Úrdrátturinn aðskilur með yfirvegun: TApiContext er lágmarksástandið sem þið viljið senda áfram. Í RemObjects SDK fer mikið fram í server-/channel-samhengi. Í heterógenum verkefnum (t.d. viðbótar worker-þræðir, DB-biðröð, bakgrunnsverkefni) er skýrt áframleiðsla oft áreiðanlegri en dulin Threadlocal-breyta, því hún gerir samhliða keyrslu og samhengisbreytingar sýnilegri.

Skilyrði: Accept-header-aðferðin gerir ráð fyrir að Reverse Proxy ykkar (nginx, IIS ARR, Traefik) sendi hausinn áfram án breytinga. Í sumum umhverfum eru „óvenjulegir“ Accept-hausar síaðir eða sameinaðir.

Gildrur: Útgáfustjórnun í gegnum Accept er aðeins eins góð og prófanir ykkar. Ef clients nota bókasöfn sem skrifa yfir Accept, getur API skyndilega fallið aftur á default. Fyrir legacy-clients er default-fallback skynsamlegt, en það verður að sjást í monitoring (t.d. log-warning „Version defaulted“).

Afbrigði: Ef þið viljið frekar hafa útgáfustýringu í X-Api-Version: Parser-inn er sá sami, einungis er uppspretta annar haus. Frá sjónarhóli gateway-a getur það stundum verið auðveldara í stjórn.

Innlimun í RemObjects SDK: Correlation-ID og Exception-Mapping við móttöku beiðna

Raunveruleg áhrif koma fram þegar þið beitið mekanískunni af fullu þunga á jaðar þjónsins: einu sinni við inngang beiðna til að lesa úr hausum, og einu sinni við undantekningarútgang til að þýða þær í stöðugt svar. Fer eftir hýsingu (t.d. RO-HTTP-Server, IIS-Hosting, sjálfstætt rekið Windows-/Windows- og Linux-services) breytast hinir nákvæmu hook-punktar; meginreglan helst alltaf sú sama: byggja upp Context, kalla á Business-Logic, mappa Exceptions miðlægt.

Í RemObjects-verkefnum er algengt að vinna beint í hverri service-aðferð. Það skalar vel í byrjun en fer síðan fram úr sér við rekstur: hver aðferð byggir upp logging og villumeðhöndlun á sinn hátt. Hreinn aðskilnaður er að hafa service-grunn eða dispatcher sem staðlaður er.

Hagnýtur ferill (meðvitað stuttur og framkvæmdarnálægur)

  1. Lesa Correlation-ID úr beiðna-hausnum X-Correlation-ID; ef hún vantar, búa hana til á þjóninum (t.d. GUID).
  2. Lesa contract-útgáfu úr Accept (eða úr X-Api-Version).
  3. Skrá byrjun beiðnar: aðferð, slóð, Correlation-ID, fjarlæg IP, hefja tímamælingu.
  4. Keyra viðskipta-lógík; umlykja DB-aðgengi með transaction þar sem unnt er.
  5. Fanga undantekningar: ákvarða HTTP-stöðu, búa til JSON-villuhlut, setja Response-haus X-Correlation-ID.
  6. Skrá endi beiðnar: stöðu, tímalengd, ef við á villukóða.

Þráðaumsjón á þjóninum: Af hverju Correlation-ID er gagnslaus án samhengisreglu

Algengt Delphi-jaðartilvik: Service-aðferðin kallar á asynkrona vinnu (t.d. skýrslugerð, innflutning, push í DMS). Þá er upphaflegi beiðna-þráðurinn ekki lengur sá sem skrifar síðar logglínur. Ef Correlation-ID er aðeins þekkt „í byrjun“, brotnar rekjanleiki niður.

Pragmatísk regla: Allt sem helst ekki strangt innan beiðna-þráðarins fær Context afhent skýrt. Jafnvel þótt það krefjist fleiri parametra í aðföngum, borgar það sig. Öðru máli má nota skýrt skilgreint Context-objekt sem meðvituðlega er afhent worker-um (í stað global breyta eða falinna singleton-a).

Typískir þröskuldarpunktar í RemObjects-/Delphi-þjónum:

  • DB-tengingar á þráð: BDE-Ablosung mit nativer Anbindung-tengingar eru ekki sjálfkrafa þráð-sækar. Connection-Pool eða ein tenging fyrir hvern þráð er oft skynsamlegri en „ein global Connection“.
  • Transaktionsgrenzen: Ef þú hefur fleiri skref innan eins request sem tilheyra sama vinnuferlinu, þarf transaction að vera í sömu röklegu einingu. Asynkrón vinna má ekki „óvart“ halda áfram í sömu transaction.
  • Cancellation: Þegar client hættir (proxy timeout, browser lokað), heldur serverinn oft áfram. Hugleiddu afdráttarlaust hvort bakgrunnsvinna hafi enn tilgang í þeim tilvikum.

Gagnaaðgangur og villukóðar: 409 er ekki „einnig 500“

Í samþættingarverkefnum skiptir hreint error-mapping meira máli en útlit. Það ræður því hvort gagnhlið (ERP-Connector, ETL-jobb, Kundenportal) getur brugðist rétt. Nokkrar hagnýtar leiðarlínur sem hafa reynst vel í Delphi/RemObjects-umhverfi:

  • 400 Bad Request: Staðfesting, vantar/ógildir parametra, JSON ekki parsanlegt. Mikilvægt: Svar ætti að vera stöðugt, jafnvel þó body sé ónýtur.
  • 401/403: Aðgreindu auðkenningu og heimild. 401 þýðir „engin/ógild auðkenning“, 403 „auðkenning í lagi, en bannað“.
  • 404: Auðlind er ekki til. Varastu að upplýsa alltaf um tilvist af öryggisástæðum.
  • 409 Conflict: Faglegur árekstur (t.d. útgáfuárekstur, „staða leyfir ekki þessa aðgerð“, brot á einstökum lykli þegar það skiptir faglega máli).
  • 422 Unprocessable Content: Þegar setningafræðilega er allt í lagi en fagleg staðfesting bilar (ekki öll teymi nota 422, en það er oft skýrara en 400).
  • 500: Allt sem þú getur ekki flokkað hreint. Innifalið er t.d. „DB down“, „timeout“, „Unhandled Exception“.

Delphi-sértækur ráður: Margir gagnagrunnsvillur koma upp sem almennar exceptions. Það borgar sig að skoða gagnaaðgangslagið sérstaklega fyrir þekktar aðstæður og umbreyta þeim í EApiError. Mikilvægt: Ekki færa SQL-brot eða innri töflu-/reitnöfn yfir í client-viðvörun. Slík atriði eiga heima í loggi, ekki í response.

Debugging-ráð: endurframkallanlegar villur með „Contract Snapshot“

Sjaldgæft en afar gagnlegt í rekstri: Vistaðu við villur (eða markvisst fyrir tiltekna Correlation-IDs) „snapshot“ af Request-Headern + Request-Body í debug-spool-skrá. Þetta er ekki varanlegt logging (persónuvernd/rúmmál), heldur stýrt tæki til að endurskapa erfitt uppgötvanleg tilfelli úr framleiðsluumhverfi.

Mikilvægt: Snapshot má aldrei vista óhindrað auth-header, tokens eða persónuupplýsingar. Í framkvæmd þýðir það: redaction (maskering) og virkjun aðeins í gegnum feature-flag eða whitelist (t.d. aðeins fyrir ákveðin Correlation-IDs, stutt tímabil).

Hreint framkvæmd í rekstri: Maskera frekar en að sleppa

Í raunverulegum samþættingum eru algengustu „gagnrýnu“ reitirnir oft þeir sem þarf til að debugga (t.d. auðkenni). Í stað þess að sleppa þeim alfarið er betra að maskera: hluta af tokeni skipta út, halda aðeins domain í netfangi, IBAN aðeins síðustu tölustafir. Svo varðveitist endurframkallanleiki málsins án þess að óþarfa gögn dreifist á skráarkerfi. Jafnframt ætti snapshotið að vera skýrt merkt sem debug-artefakt og hafa skilgreindan geymslutíma.

Öryggi og rekstur: Hausaframsending, proxy-keðjur og tímamörk

Sjaldan endar REST API beint hjá viðskiptavininum. Algengt er keðja af Reverse Proxy, TLS-Termination, WAF eða API-Gateway. Af þessu leiða nokkur hagnýt atriði:

  • Remote IP: Treystið ekki blindandi á X-Forwarded-For. Takið það aðeins frá traustum proxy-um og notið annars beina socket-IP. Í rekstrarskírteinum ætti að koma fram hvaða hops eru „trusted“.
  • Tímamörk: Ef proxy-ið hefur 30 sekúndur en backend-ið ykkar þarf 2 mínútur, munuð þið búa til ghost-requests. Stillið tímamörk samkvæmilega eftir allri keðjunni og takið ákvörðun: samstillt request eða job-mynstur (202 Accepted + status-endapunktur).
  • Correlation-ID: Setjið Correlation-ID í response-hausana svo kerfisstjórar geti sameinað hana úr loggum og á klientsíðunni. Ef gateway notar eigin request-IDs: skrifið og kortleggingu báða IDs.
  • Villutextar: Í framleiðslurekstri engar innri upplýsingar. Debug-upplýsingar aðeins undir stjórn (Stage/Feature-Flag) og, í vafa, eingöngu í logginu.

Mat: Af hverju RemObjects SDK getur haft forskot hér

Í Delphi-vistkerfum eru REST-þjónar oft byggðir með léttari ramma (t.d. minimalistískir HTTP-routerar). RemObjects SDK nýtir styrk sinn þegar þið hafið eða þurfið fjölþrepa arkitektúr:

  • Skýr þjónustumörk: Þjónustu‑aðferðir eru skýrar og samningsviðmót (Contracts) má útgáfustýra.
  • Flutningur og serialisierung: Þið getið talað JSON, en einnig önnur skilaboðaform (eftir uppsetningu), án þess að menga faglogikuna.
  • Rekstur: Hýsingarvalkostir og samþætting í núverandi Windows- og Linux-þjónustur er hægt að plana, þar með taldar hreinar rollouts.

Sýnt nálgun fyllir upp í þau atriði sem oft vantar í daglegum rekstri: einheitleg villaobjekt, determinísk útgáfustýring og skráning sem hægt er að tengja saman. Sérstaklega fyrir sérsniðna fyrirtækjahugbúnað með löngum líftíma sparar þetta tíma við uppfærslur og samþættingu ytri kerfa.

Niðurstaða: Er tilkostnaðurinn þess virði — og hvar fer nálgunin úr böndunum?

Ávinningurinn kemur fram þegar REST-viðmótið ykkar ekki aðeins „virkar“, heldur er það varanlega rekjanlegt: stöðugar JSON-samningar, útgáfustýring án URL-villuframdráttar, skiljanlegar villur og villuleit án ágiskana. Einmitt þar er nálgunin með context, Correlation-ID og miðstýrðu exception-mapping í RemObjects SDK öflug.

Takmarkanir í notkun: Ef þið eruð með einn einangraðan, skammlífan endapunkt án samþættingaraðila, getur Media-Type-útgáfustýring fljótt verið overengineering. Einnig er Snapshot-Logging aðeins réttmætt ef Redaction og virkjun eru innleidd af aga. Og: ef proxy-stakkinn ykkar „hagræðir“ eða fjarlægir hausana, þarfð þið fyrst að leiðrétta innviði, annars munið þið vera að villuleita á röngum stigi.

Ef þið eruð að modernisera núverandi Delphi-þjónalandslag eða þurfið að samþætta ferlisnæma hugbúnaðarlausn á hreinan hátt inn í ERP/DMS/CRM, eru þessir mekanismar oft munurinn á milli „läuft im Test“ og „läuft im Betrieb“.

Í faglegu umhverfi gegna einnig Delphi REST-API og REST-þjónn og Remobjects Sdk Delphi mikilvægu hlutverki, þegar samþættingar, gagnaflæði og áframhaldandi þróun þurfa að virka samhæft.

Ræddu verkefni eða endurnýjunaráform með Net-Base.

Næsta skref

Ef efnið verður að raunverulegu verkefni, ætti snemma að skoða kerfisarkitektúr, núverandi kerfi og rekstur í sameiningu.

Við styðjum ekki aðeins við einstakar spurningar, heldur einnig þegar úr kóðabútum, eldri kerfum eða gáttahugmyndum þarf að verða traust fyrirtækjaverkefni.

  • Núverandi staða, markmynd og tæknileg áhætta eru metin saman.
  • REST, aðgangur að gögnum, gáttir og innleiðing verða ekki flutt til síðari tíma sem afleiðingar.
  • Þú sérð snemma hvaða leið er efnahagslega og rekstrarlega framkvæmanleg.

Deila færslu

Deila þessari færslu beint

LinkedIn, X, XING, Facebook, WhatsApp og tölvupóstur eru strax í boði. Fyrir Instagram undirbúum við tengil og stuttan texta strax.

Tölvupóstur

Instagram opnast í nýjum flipa. Tengill og stuttur texti eru afritaðir í klippiborðið á undan.