Net-Base Maġazin

09.06.2026

REST API ma' RemObjects SDK: gestjoni tal-verżjoni u debug ta' endpoints JSON b'mod nadif (Delphi fragment tal-kodiċi sors)

Kif tibni bil-RemObjects SDK f'Delphi API REST li ma tinfraggarx fil-produzzjoni: kuntratti JSON stabbli, versioning mingħajr proliferazzjoni tal-URL, Correlation-ID permezz tas-saffi kollha, Error-Mapping ċentrali, Snapshot-Logging għal każijiet diffiċli ta' debug u pariri prattiċi...

09.06.2026

Minn suġġett tar-rivista għall-prattika tal-proġett

Paġni ta' servizz u paġni tekniċi relevanti għall-artiklu

Għaliex „REST API ma‘ RemObjects SDK“ fil-prattika spiss tiddeċiedi fuq il-fruntieri

Servizz „Hello World“ ftit drabi jiddetermina s-suċċess ta‘ REST API ma‘ RemObjects SDK; ir-riżultat spiss jiddependi fuq il-postijiet fejn il-operat, il-legacy u l-integrazzjoni jiltaqgħu: verżjoni mingħajr staġnazzjoni, mġieba konsistenti ta‘ żball fuq l-endpoints kollha, debugging riproduċibbli f’ċrieki ta‘ proxy u l-abbiltà li tikkorrelata b’mod univoku r-requests f’każ ta‘ problema.

RemObjects SDK jipprovdi ħafna infrastruttura għal dan: services, formati tal-messaġġi, serializzazzjoni, hosting (pereżempju bħala Windows- u Linux-Services jew wara IIS/Reverse Proxy) u punti definiti biex jimmaniġġjaw żbalji b’mod ċentralizzat. Dak li spiss jonqos f’ambjenti ta‘ software tan-negozju żviluppati huwa kuntratt konsistenti u sod: liema campi JSON huma stabbli? Kif ninfurmaw dwar żbalji? Kif nirrikonoxxu request meta jgħaddi mill-load balancer, TLS-termination u bosta saffijiet ta‘ backend?

Il-metodu li ġej (inkluż snippet ta‘ Delphi) juri linja robusta għal RemObjects SDK: versioning ta‘ kuntratti JSON, Correlation-ID (Request-ID għall-traċċar) imposta bħala obbligu, it-traduzzjoni ta‘ Exceptions f’Status HTTP u f’oġġetti ta‘ żball JSON u liema mod ma nippermettu l-ebda konflitt bejn debugging u operat. Barra minn hekk, nindirizzaw każijiet ta‘ bżonn li fil-prattika jseħħu regolarment: threading fuq is-server, aċċessi għad-database fl-ambitu ta‘ BDE-ablożjoni b’konnessjoni nattiva, header tal-proxy, timeouts u payloads tal-client “mifxula”.

Deċiżjoni tal-arkitettura: immaniġġjar tal-verżjonijiet permezz tal-Media Type minflok l-URL

Ħafna APIs jimmaniġġjaw il-verżjoni fuq it-toroq bħall-/v1/. Dan hu pragmatiku, imma f’integrazzjonijiet li jdumu żmien twil (pereżempju konnessjonijiet ERP/DMS/CRM) dan joħloq duplicazzjoni ta‘ URL, rotot doppji, testijiet doppji u t-tħassib “liema verżjoni qed nużaw?” fil-manwali tal-operat.

Alternattiva hi l-verżjoni permezz tal-Media Type (Content Negotiation). Il-client jibgħat, pereżempju, Accept: application/vnd.company.order+json;v=2. Is-server jaqra d-dejta tal-verżjoni b’mod deterministiku u jadatta l-imġiba tal-kuntratt/DTO skontha. Dan jaħdem f’ċrieki ta‘ proxy u cache jekk il-headers jiġu trasferiti b’mod nadif. Għal amministraturi hu wkoll faċli li jivverifikaw: request jista‘ jiġi riprodott bi Curl/Postman mingħajr ma jinbidel l-URL.

RemObjects SDK mhuwiex “REST-puristiku”, imma framework pragmaticu għall-services. Eżatt minħabba dan, il-varjant tal-Media Type għandu sens: tista‘ żżomm endpoints stabbli u tibqa‘ tevita t-tneħħija ta‘ stabilità waqt li tevita l-ħtiġijiet ta‘ evoluzzjoni tal-kuntratti. Il-punt importanti huwa li dejjem tħaddem il-valutazzjoni tal-verżjoni, tiddeċiedi f’post ċentralizzat u tdaħħal ir-riżultat fil-kuntest tas-servizz tiegħek.

Meta taqa‘ l-approċċ tal-Accept-Header?

Fil-prattika hemm tliet punti ta‘ ksur tipċi li wieħed għandu jindirizza minn qabel:

  • Politiki tal-proxy: Xi Reverse Proxies/regoli tal-WAF jinnormalizzaw jew jiffiltraw l-Accept-Header. F’dak il-każ l-API tiegħek terġa‘ tinżel silentament lejn il-valur default. Soluzzjoni: ivverifika b’mod espliċitu r-regoli tal-proxy; jekk meħtieġ, uża X-Api-Version bħala fallback.
  • Libreriji tal-client: Xi HTTP-clients jissettjaw Accept-Header proprji u jisħqu l-valuri tiegħek. Soluzzjoni: appoġġja l-verżjoni tal-kuntratt ukoll bħala parametru ta‘ query fakultattiv (bħala fallback biss), jew parsa l-Accept-Header server-side b’tolleranza.
  • Cache: Wenn Response-Caching im Spiel ist, muss der Cache nach Accept variieren (Vary: Accept), sonst liefert er Version 1 an Version-2-Clients. Lösung: Vary bewusst setzen, oder Caching auf API-Ebene deaktivieren.

Snippet tas-sors: Request-Context, Correlation-ID, Verżjoni u Error-Mapping

Il-kodiċi huwa maqsum b’mod intenzjonat sabiex jintegra f’proġetti eżistenti ta‘ RemObjects-Server: saff żgħir ta‘ context, parser għall-verżjoni tal-API (mill-Accept), mekkaniżmu ta‘ Correlation-ID u mapping ċentrali tal-eċċezzjonijiet. Termini:

  • Correlation-ID: ID unika għal kull request li tidher fil-response u tiġi riferuta fil-logs.
  • Exception-Mapping: Traduzzjoni ta‘ eċċezzjonijiet interni Delphi f’oġġetti ta‘ żball stabbli u li jistgħu jiġu proċessati mill-klijent (inkl. HTTP-Status).
  • Contract-Version: Il-verżjoni tal-kuntratt JSON li tikkontrolla l-imġieba u l-kampi.
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.

Għan: Kuntext stabbli tal-Request minflok „xi mkien fil-Threadlocal“

Is-snipsel jaqsam b’mod intenzjonat: TApiContext hu l-istat minimu li trid tgħaddi. F’RemObjects SDK ħafna funzjonijiet jaħdmu fuq kuntest tas-Server/Channel. F’proġetti eterogeni (eż. worker-threads addizzjonali, DB-Queue, jobs fil-isfond) it-tgħaddi esplicitu tal-kuntest huwa spiss aktar robust minn Threadlocals impliċiti, għax jagħmel il-konkorrenza u t-tibdil tal-kuntest aktar viżibbli.

Kundizzjonijiet: Il-varjant tal-Accept-Header jinvolvi li r-reverse proxy tiegħek (nginx, IIS ARR, Traefik) jibgħat il-header mingħajr bidla. F’xi ambjenti headeri “inkuriti” jew mhux standard jistgħu jiġu filtrati jew aggregati.

Trappoli: Il-versioning permezz tal-Accept huwa daqs kemm tajjeb kemm huma t-testijiet tiegħek. Jekk il-klijenti jużaw libreriji li jiktbu mill-ġdid l-Accept, API tista‘ waħda taqbeż lura għall-default. Għal klijenti legacy, fallback default huwa sensibbli, iżda jridu jidhru fil-monitoraġġ (eż. twissija fil-log “Version defaulted”).

Varjanti: Jekk tirreferi l-versioning b’mod preferenzjali permezz ta‘ X-Api-Version: il-parser jibqa‘ l-istess, biss is-sors huwa header differenti. Minn perspettiva ta‘ gateways dan kultant ikun aktar faċli biex jikkontrolla.

Integrazjoni f‘ RemObjects SDK: Correlation-ID u Exception-Mapping fil-bidu tas-servizz

Il-benefiċċju reali jseħħ meta tapplika l-mekkaniżmu konsekwentement fil-periferija tas-server tiegħek: waħda darba aqra mill-header meta jidħol il-request, u darba oħra tradużih f’respons stabbli meta toħroġ exception. Skont il-hosting (eż. RO-HTTP-Server, IIS-Hosting, servizzi Windows-/Windows- u Linux-Services mħaddma minnkom stess) il-punti tal-hook konkretament se jvarjaw; il-prinċipju jibqa‘ l-istess: ibni l-Context, sejjaħ il-business-logic, mapja l-Exceptions centralment.

F’proġetti RemObjects spiss jaħdmu direttament għal kull metodu tas-servizz. Fil-bidu dan jiskala tajjeb, imma fil-produzzjoni jinqasam: kull metodu jibni logging u ġestjoni tal-żbalji b’mod differenti. Qasam nadif huwa Bażi tas-Servizz jew Dispatcher standardizzat.

Proċess prattiku (b’mod konxju qasir u qrib tal-implimentazzjoni)

  1. Aqra l-Correlation-ID mill-Request-Header X-Correlation-ID; jekk nieqsa, ġeneraha min-naħa tas-server (eż. GUID).
  2. Aqra l-Contract-Version minn Accept (jew minn X-Api-Version).
  3. Irreġistra l-bidu tar-request: metodu, path, Correlation-ID, Remote IP, ibda kejl tad-durata.
  4. Esegwixxi l-business-logic; kapsla l-aċċessi tal-DB kemm jista‘ jkun transazzjonalment.
  5. Aqbad l-exception: determina l-HTTP-Status, ġenera oġġett ta‘ żball JSON, issetta r-Response-Header X-Correlation-ID.
  6. Irreġistra t-tmiem tar-request: status, durata, u jekk hemmx, kodiċi ta‘ żball.

Threading fis-Server: Għaliex Correlation-ID mingħajr disiplina tal-kuntest issir bla valur

Każ ta‘ bord komuni f’Delphi: il-metodu tas-servizz jattiva xogħol asincroniku (eż. ġenerazzjoni ta‘ rapporti, import, push f’DMS). F’dak il-każ it-thread tal-request oriġinali m’għadux dak li jikteb il-linji tal-log wara ftit. Jekk il-Correlation-ID tkun magħrufa biss “fil-bidu”, il-trackability tinfetaħ.

Regola pragmatika: Kollox li mhux strettament jibqa‘ fit-thread tar-request għandu jitħalla jmur bil-Context mgħaddi b’mod esplicitu. Anki jekk dan jidhirli bħala lista ta‘ parametri iżjed, jiswa. Alternattivament tista‘ taħdem bi oġġett ta‘ kuntest imdefinit b’mod ċar li jingħata lill-worker b’mod esplicitu (minflok varjabbli globali jew singletons moħbija).

Punti kritiċi tipċi f’server RemObjects-/Delphi:

  • DB-Connections pro Thread: BDE-Ablosung mit nativer Anbindung-Verbindungen sind nicht automatisch thread-sicher teilbar. Ein Connection-Pool oder pro Thread eine Verbindung ist häufig sinnvoller als „eine globale Connection“.
  • Limiti tat-tranżazzjoni: Wenn Sie innerhalb eines Requests mehrere Schritte haben, die zusammengehören, muss die Transaktion in der gleichen logischen Einheit bleiben. Asynchrone Arbeit darf nicht „aus Versehen“ in der gleichen Transaktion weiterlaufen.
  • Annullament: Wenn der Client abbricht (Proxy timeout, Browser closed), läuft der Server oft weiter. Überlegen Sie bewusst, ob Hintergrundarbeit dann noch Sinn ergibt.

Aċċess tad-dejta u kodiċijiet ta‘ żball: 409 ist nicht „auch ein 500“

F’Integrationsprojekten ist sauberes Error-Mapping mehr als Kosmetik. Es entscheidet, ob ein Gegenüber (ERP-Connector, ETL-Job, Portal tal-klijent) korrekt reagieren kann. Ein paar praxisnahe Leitplanken, die sich in Delphi/RemObjects-Umgebungen bewährt haben:

  • 400 Bad Request: Validierung, fehlende/ungültige Parameter, JSON nicht parsebar. Wichtig: Die Antwort soll stabil bleiben, auch wenn der Body kaputt ist.
  • 401/403: Authentifizierung vs. Berechtigung trennen. 401 bedeutet „keine/ungültige Identität“, 403 „Identität ok, aber verboten“.
  • 404: Ressource existiert nicht. Vorsicht bei Security: Nicht immer verraten, ob etwas existiert.
  • 409 Conflict: Fachlicher Konflikt (z. B. Versionskonflikt, „Status erlaubt diese Aktion nicht“, eindeutige Schlüsselverletzung, wenn sie fachlich relevant ist).
  • 422 Unprocessable Content: Wenn syntaktisch alles ok ist, aber fachliche Validierung scheitert (nicht jedes Team nutzt 422, aber es ist oft klarer als 400).
  • 500: Alles, was Sie nicht sauber klassifizieren können. Dazu gehört auch „DB down“, „Timeout“, „Unhandled Exception“.

Delphi-spezifischer Kniff: Viele DB-Fehler kommen als generische Exceptions hoch. Es lohnt sich, an der Datenzugriffsschicht gezielt auf bekannte Situationen zu prüfen und sie in EApiError zu überführen. Wichtig dabei: Keine SQL-Fragmente oder internen Tabellen-/Spaltennamen in die Client-Message übernehmen. Diese Details gehören ins Log, nicht in die Response.

Teknika ta‘ Debugging: reproduzierbare Fehler durch „Snapshot tal-kuntratt“

Ungewöhnlich, aber im Betrieb extrem hilfreich: Speichern Sie bei Fehlern (oder gezielt bei bestimmten Correlation-IDs) einen „Snapshot“ aus Request-Headern + Request-Body in einer Debug-Spool-Datei. Das ist kein Dauerlogging (Datenschutz/Volumen), sondern ein kontrolliertes Werkzeug, um schwer reproduzierbare Fälle aus Produktionsnähe nachzustellen.

Wichtig: Ein Snapshot darf niemals ungefiltert Auth-Header, Tokens oder personenbezogene Daten persistieren. In der Praxis bedeutet das: Redaction (Maskierung) und Aktivierung nur über Feature-Flag oder Whitelist (z. B. nur für bestimmte Correlation-IDs, kurze Zeitfenster).

Saubere Umsetzung in der Praxis: Maskieren statt Weglassen

In echten Integrationen sind gerade die „kritischen“ Felder oft die, die man zum Debuggen bräuchte (z. B. Identifikatoren). Statt pauschalem Weglassen ist Maskieren besser: Token teilweise ersetzen, E-Mail nur Domain behalten, IBAN nur die letzten Ziffern. So bleibt der Fall reproduzierbar, ohne unnötige Daten im Dateisystem zu verteilen. Zusätzlich sollte der Snapshot klar als Debug-Artefakt gekennzeichnet sein und eine definierte Aufbewahrungszeit haben.

Sigurtà u Operazzjoni: Trasferiment tal-header, katini ta‘ proxy u timeouts

Una REST API tispiċċa rari direttament fuq il-klijent. Tipikament ikunu katini ta‘ Reverse Proxy, TLS-Termination, WAF jew API-Gateway. Minn dan joħorġu punti prattiċi:

  • Remote IP: Taqbilx bla dubju fuq X-Forwarded-For. Aċċetta biss minn proxies affidabbli, inkella uża l-IP tas-socket dirett. Fil-manwali tal-operazzjoni għandu jkun speċifikat liema hops huma „trusted“.
  • Timeouts: Jekk il-proxy għandu 30 sekonda u l-backend tiegħek jeħtieġ 2 minuti, toħloq Ghost-Requests. Imponi timeouts konsistenti tul il-katina u iddeċiedi: Request sinkronu jew Job-Pattern (202 Accepted + Status-Endpunkt).
  • Correlation-ID: Poġġi l-Correlation-ID fil-response-Header, sabiex l-amministraturi jkunu jistgħu jikkorrisponduha bejn il-logs u n-naħa tal-klijent. Jekk gateway juża Request-IDs proprji: irrekordja u mappa iż-żewġ IDs.
  • Fehlertexte: Fil-produzzjoni m’għandhomx jinkixfu dettalji interni. Dettalji ta‘ debug biss f’mod kontrollat (Stage/Feature-Flag) u, jekk meħtieġ, biss fir-log.

Kuntest: Għaliex RemObjects SDK jista‘ jkollu vantaġġ hawn

F’ekosistemi Delphi spiss jinbnew REST-Server b’frameworks aktar ħfief (eż. HTTP-router minimalisti). RemObjects SDK juri s-saħħa tiegħu meta diġà għandek, jew teħtieġ, arkitettura multi-saff:

  • Klare Service-Grenzen: Il-metodi tas-servizz huma espliciti, u l-kuntratti jistgħu jiġu verżjonati.
  • Transporte und Serialisierung: Tista‘ titkellem JSON, imma wkoll formati oħra ta‘ messaġġ (skont il-setup), mingħajr ma tħallat il-loġika tan-negozju.
  • Betrieb: Għażliet ta‘ hosting u l-integrazzjoni fis-Windows- u Linux-Services eżistenti jistgħu jiġu pjanati, inkluż rollouts nadifa.

L-approċċ murija jżid dan b’elementi li fil-prattika spiss jonqsu: oġġetti ta‘ żball uniformi, verżjoni deterministika u logging korrelabbli. Speċjalment f’software korporattiv personalizzat b’ċikli twal ta‘ ħajja, dan jiffranka ħin fl-aġġornamenti u fl-integrazzjoni ta‘ sistemi esterni.

Konklużjoni: Jiswa l-isforz — u fejn jaqa‘ dan l-approċċ?

Il-valur joħroġ meta l-interface REST tiegħek mhux biss „taħdem“, iżda tkun tista‘ tiġi mmaniġġjata fuq termini twal: kuntratti JSON stabbli, verżjoni mingħajr proliferazzjoni ta‘ URL, żbalji li jistgħu jiġu segwiti u debugging mingħajr logħob tal-guess. Eżatt f’dak il-punt l-approċċ bil-Context, Correlation-ID u exception-mapping ċentrali fi RemObjects SDK ikun b’saħħtu.

Limitazzjonijiet tal-użu: Jekk għandek biss endpoint wieħed, qasir u bla sħab ta‘ integrazzjoni, il-media-type-versioning jista‘ jidhirlek malajr bħala overengineering. Anke snapshot-logging għandu sens biss jekk timplimenta Redaction u l-attivazzjoni b’diżiplina. U: jekk il-proxy-stack tiegħek ‚jottimizza‘ jew jneħħi headers, trid l-ewwel tirranġa l-infrastruttura, inkella tkun qed tiddubbugja s-saff ħażin.

Jekk trid modernizza pajsaġġ ta‘ server Delphi eżistenti jew tintegra soluzzjoni software qrib il-proċess b’mod nadif f’ERP/DMS/CRM, dawn il-meccanismi spiss huma d-differenza bejn „jaħdem fit-test“ u „jaħdem fl-operazzjoni“.

Fil-qasam professjonali jilagħbu wkoll Delphi REST-API u REST-Server u Remobjects Sdk Delphi rwol importanti, meta l-integrazzjonijiet, il-flussi tad-dejta u t-titjib kontinwu jridu jaħdmu flimkien b’mod nadif.

Iddiskutu proġett jew inizjattiva ta‘ modernizzazzjoni ma‘ Net-Base.

Pass li jmiss

Meta suġġett jiġi mwettaq bħala proġett reali, l-arkitettura, is-sistema eżistenti u l-operat għandhom jiġu kkunsidrati flimkien kmieni.

Aħna nappoġġjaw mhux biss f'kwistjonijiet puntwali, iżda wkoll meta biċċiet ta' kodiċi sors, temi legacy jew ideat għal portali jridu jsiru proġett korporattiv stabbli u affidabbli.

  • L-istat attwali, l-istat tal-mira u r-riskji tekniċi jiġu vvalutati flimkien.
  • REST, aċċess tad-dejta, portalijiet u rollout ma jiġu posposti bħala konsegwenzi tardivi.
  • Tara kmieni liema triq hija ekonomika u operattivament sostenibbli.

Aqsam il-post

Aqsam dan il-post direttament

LinkedIn, X, XING, Facebook, WhatsApp u E-Mail huma disponibbli immedjatament. Għal Instagram nippreparaw il-link u test qasir direttament.

Imejl

Instagram jiftaħ f'tab ġdid. Il-link u t-test qasir jiġu kkopjati qabel fil-clipboard.