Net-Base Iris

09.06.2026

REST API le RemObjects SDK: endpóintí JSON a leaganú go soiléir agus a dhífhabhtú (Delphi sleachta cód foinse)

Conas API REST a thógáil le RemObjects SDK i Delphi nach mbrisfidh i mbun oibre: conarthaí JSON seasmhacha, versionáil gan scaipeadh URLanna, Correlation-ID trí gach sraith, mapáil earráide lárnach, Snapshot-Logging do chásanna dian-dífhabhtaithe agus leideanna praiticiúla...

09.06.2026

Ó théama an iris go cleachtas tionscadail

Leathanaigh seirbhíse agus teicniúla oiriúnacha don alt

Cén fáth a bhíonn „REST API le RemObjects SDK“ ag cinneadh go minic sna himtharraingí sa phraxis

Ní bhíonn rath nó teip REST API le RemObjects SDK go minic ag an seirbhís “Hello World”, ach sna háiteanna ina mbuaileann oibriú, córais oidhreachta agus comhtháthú: leaganú gan stad, iompraíocht earráide comhsheasmhach trasna gach pointe deiridh, debugging in-athshamhlaithe i slabhraí proxy agus an cumas iarratais a chomhghaolú go soiléir i gcás fadhb.

Cuireann RemObjects SDK go leor bonneagair ar fáil dó sin: seirbhísí, formáidí teachtaireachta, sraithiú, óstáil (m.sh. mar Windows- agus Linux-Services nó taobh thiar de IIS/Reverse Proxy) agus pointí sainmhínithe chun earráidí a láimhseáil go lárnach. I ndálaí ina bhfuil líonra bogearraí gnó forbartha, áfach, is minic nach bhfuil conradh leanúnach soiléir: Cén réimsí JSON atá seasmhach? Conas a chomharthaímid earráidí? Conas a aithnímid iarratas arís nuair atá sé tar éis dul tríd Load Balancer, TLS-Termination agus il-sraitheanna backend?

Cuireann an cur chuige seo a leanas (ina bhfuil snipsel Delphi) líne chobhsaí do RemObjects SDK i láthair: conarthaí JSON a leaganú, Correlation-ID (Request-ID le haghaidh rianaithe) a éileamh, Exceptions a thiontú go stádas HTTP agus go réada earráide JSON agus Debugging agus Oibriú a choinneáil mar phróisis chomhlántacha seachas i gcoinne a chéile. Breise, déanaimid athbhreithniú ar fhadhbanna imeallacha a thagann chun cinn go rialta i dtimpeallachtaí beoga: threading ar an freastalaí, rochtain ar bhunachar sonraí agus BDE-aibhléisiú le ceangail dhúchais, headers proxy, timeouts agus payloadaí cliant “salacha”.

Cinneadh ailtireachta: Leaganú tríd an Media Type seachas URL

Leaganann go leor APIanna trí riananna mar /v1/. Tá sé sin praiticiúil, ach i gcomhtháthuithe atá i gcomhairle fada (m.sh. nascanna ERP/DMS/CRM) cruthaíonn sé minic dúbailtí URL, rianruithe dúbailte, tástálacha dúbailte agus an cheist “Cén leagan a úsáideann muid i ndáiríre?” sna lámhleabhair oibriúcháin.

Mar mhalairt is féidir leaganú a dhéanamh tríd an Media Type (Content Negotiation). Seolann an cliant, m.sh., Accept: application/vnd.company.order+json;v=2. Léann an freastalaí an leagan go diongbháilte agus coigeartaíonn sé iompraíocht an Chonartha/DTO dá réir. Oibríonn sé sin i slabhraí proxy agus cache má thrasdaitear na heaidirghabhálacha (headers) go glan. Tá sé soiléir le haghaidh riarthóirí freisin: is féidir iarratas a atshamhlú le Curl/Postman gan athrú sna URLs.

Ní hé RemObjects SDK an cur chuige “REST-puristic”, ach fráma seirbhísí pragmatach é. Dá bharr sin, tá buntáiste sa mhodh Media-Type: is féidir leat deimhniú deiridh seasmhach a choinneáil agus iad fós conarthaí a fhorbairt. Tá sé ríthábhachtach an leagan a léiriú i gcónaí, cinneadh a dhéanamh go lárnach i bpointe amháin agus an toradh a bheith curtha isteach i gcomhthéacs do sheirbhís.

Cathain a theipeann an éagsúlacht Accept-Header?

Sa phraxis tá trí bhriseadh tipiciúil ar chóir iad a chur san áireamh roimh ré:

  • Beartais Proxy: Rialaíonn roinnt Reverse Proxies/WAF an Accept-Header nó scagann siad é. Ansin filleann do API go ciúin ar an réamhshocrú. Réiteach: seiceáil rialacha an proxy go soiléir, agus más gá dul i muinín X-Api-Version mar fhillteoir.
  • Leabharlanna Cliant: Socraíonn roinnt cliaint HTTP a Accept-Header féin agus scríobhann siad thar na luachanna. Réiteach: tacú le leagan an chonartha freisin mar pharaiméadar ceiste roghnach (mar fhillteoir amháin), nó an Accept-Header a pharsáil go foighneach ar thaobh an fhreastalaí.
  • Cacheáil: Má tá cacheáil freagartha i bhfeidhm, caithfidh an cache éagsúlú de réir Accept (Vary: Accept), murach sin seolfar Leagan 1 chuig cliaint Leagan 2. Réiteach: socraigh an Vary go soiléir, nó déan cacheáil ar leibhéal na API a dhíchumasú.

Sníocht Foinse: Request-Context, Correlation-ID, Version agus Error-Mapping

Tá an cód socraithe go cúramach ionas gur féidir é a chomhtháthú i dtionscadail RemObjects-Server atá ann cheana: sraith bheag Context, parser don leagan API (as Accept), meicníocht Correlation-ID agus Exception-Mapping lárnach. Coincheapa:

  • Correlation-ID: Aitheantas uathúil in aghaidh gach iarratais, a bhíonn le fáil arís sa fhreagra agus a úsáidtear sna logaí.
  • Exception-Mapping: Aistriú eisceachtaí inmheánacha Delphi go réada earráide seasta, inbhainistithe ag an gcliant (lena n-áirítear stádas HTTP).
  • Contract-Version: Leagan den chonradh JSON a rialaíonn an iompar agus na réimsí.
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.

Cuspóir: Comhthéacs Iarratais Seasmhach in ionad „ar bith sa Threadlocal“

Tá an snipsel ag scaradh go díreach: TApiContext is é an staid íosta a theastaíonn uait a tharchur. Sa RemObjects SDK rithtear go leor tríd an gcomhthéacs freastalaí/chainéil. I dtionscadail ilchineálacha (m.sh. snáitheanna oibre breise, DB-Queue, postanna cúlra) bíonn sé go minic níos iontaofa an comhthéacs a tharchur go soiléir seachas brath ar Threadlocals impliceacha, toisc go ndéanann sé an chomhthráthúlacht agus an t-aistriú comhthéacs níos infheicthe.

Coinníollacha: Tá an leagan bunaithe ar Accept-Header ag brath ar do Reverse Proxy (nginx, IIS ARR, Traefik) an header a chur ar aghaidh gan é a athrú. I roinnt timpeallachtaí scagfar nó comhtháthófar Accept-Header a mhalairt de ghnáth.

Rioscaí: Tá an leaganú tríd Accept chomh maith leis na tástálacha atá agat. Má úsáideann cliaint leabharlanna a chléirsíonn nó a athscríobhann Accept, d’fhéadfadh an API titim ar ais go réamhshocrú go tobann. Do chliaint legacy d’fhéadfadh fallback réamhshocraithe a bheith ciallmhar, ach ní mór é sin a bheith infheicthe i do mhonatóireacht (m.sh. rabhaidh loga „Version defaulted“).

Roghanna: Más fearr leat an leaganú a dhéanamh trí X-Api-Version: tá an parser mar an gcéanna, is é an t-aon difríocht ná gur header eile an fhoinse. Ó thaobh rialaithe goitreán (gateways) de, bíonn sé uaireanta níos éasca é sin a rialú.

Comhtháthú i RemObjects SDK: Correlation-ID agus Exception-Mapping ag Iontráil an tSeirbhíse

Tarlaíonn an tionchar i ndáiríre nuair a chuirtear an mheicnic i bhfeidhm go leanúnach ar imeall do fhreastalaí: léigh ceann amháin as na headers ag iontráil an iarratais, agus aistrigh ceann amháin ag aschur eisceachta go freagra seasmhach. Ag brath ar an óstáil (m.sh. RO-HTTP-Server, IIS-Hosting, seirbhísí Windows-/Windows- agus Linux-Services) beidh na poiintí hook sonracha éagsúil; fanann an prionsabal céanna: tóg comhthéacs, glaoigh ar an lógic ghnó, mapáil eisceachtaí go lárnach.

I bhproicéid RemObjects oibrítear go minic go dhíreach ar leibhéal gach modh seirbhíse. Ar dtús scálaíonn sé go maith, ach sa bhainistíocht casann sé: tá gach modh ag cur logging agus láimhseáil earráidí i bhfeidhm ar bhealach éagsúil. Geallfaidh gearradh glan ar leithligh mar Bonn SeirbhíseRiarálaí caighdeánú agus inrochtaineacht.

Sruth Oibre Práitiúil (go cúramach gearr agus gar don chur i bhfeidhm)

  1. Léigh Correlation-ID ó Request-Header X-Correlation-ID; má tá sí ar iarraidh, gineann an freastalaí í (m.sh. GUID).
  2. Léigh an leagan conartha ó Accept (nó ó X-Api-Version).
  3. Logáil tús an iarratais: modh, cosán, Correlation-ID, IP iargúlta, tosú tomhais fad.
  4. Rith an lógic ghnó; pacáil rochtain ar DB chomh transeacúil agus is féidir.
  5. Gabh eisceacht: socraigh stádas HTTP, cruthaigh réad earráide JSON, socraigh Response-Header X-Correlation-ID.
  6. Logáil deireadh an iarratais: stádas, fad, más infheidhme cód earráide.

Snáitheáil sa Freastalaí: Cén fáth nach bhfuil Correlation-ID úsáideach gan disciplín maidir le comhthéacs

Cás imeall coitianta Delphi: spreagann modh seirbhíse obair asíncrónach (m.sh. gineadh tuarascála, allmhairiú, push isteach i DMS). Ansin ní hé an snáithe iarratais bunaidh an ceann a scríobhfaidh na línte loga níos déanaí. Má theorannófar an Correlation-ID go ‚ag an tús‘ amháin, titfidh an inchúlaitheacht.

Rial pragmatach: tabhair an Comhthéacs go soiléir do gach rud nach bhfágtar go docht sa snáithe iarratais. Cé go bhféadfadh sé sin cuma a thabhairt ar liosta paraiméadar níos faide, íocann sé siar i dtéarmaí diagnóise agus monatóireachta. Mar mhalairt is féidir oibriú le réad comhthéacs shonraithe a gcuirtear ar fáil go follasach do workers (in áit athróga domhanda nó singiltonanna ceilte).

Poiintí tipping tipiciúla i bhfreastalaithe RemObjects-/Delphi:

  • Nascanna DB in aghaidh snáithe: BDE-Ablosung mit nativer Anbindung-nascanna ní roinntear go huathoibríoch go sábháilte idir snáithí. Is minic go mbíonn pool nascanna nó nasc in aghaidh an snáide níos ciallmhaire ná „nasc domhanda“.
  • Teorainneacha idirbheart: Má tá roinnt céimeanna laistigh d’iarratas a bhaineann lena chéile, caithfidh an idirbheart fanacht mar an aonad loighciúil céanna. Níor chóir go leanfadh obair asíncrónach gan choinne san idirbheart céanna.
  • Cealú: Má bhriseann an cliant an ceangal (eagtha ama an Proxy, brabhsálaí dúnta), is minic go leanann an freastalaí ag rith. Smaoinigh go cúramach an bhfuil ciall le hobair chúlra ansin.

Rochtain sonraí agus cóid earráide: Níl 409 „mar 500“

I dtionscadail chomhtháthaithe tá léarscáil earráide ghlan níos mó ná cosmaideach. Socraíonn sí an féidir le comhpháirtí (ERP-Connector, ETL-Job, Portál Custaiméirí) freagairt i gceart. Seo roinnt treoirlínte praiticiúla a d’oibrigh i dtimpeallachtaí Delphi/RemObjects:

  • 400 Bad Request: Bailíochtú, paraiméadair ar iarraidh/nárbh bailí, JSON nach bhfuil inbhainisteach. Tábhachtach: Ba chóir go mbeadh an freagra seasmhach, fiú má tá an comhlacht truaillithe.
  • 401/403: Scar fíordheimhniú ó údarás. Ciallaíonn 401 „gan/aitheantas neamhbhailí“, 403 „aitheantas ceart, ach cosc“.
  • 404: Níl an acmhainn ann. Bí cúramach ó thaobh slándála: níor chóir i gcónaí a nochtadh an bhfuil rud ann.
  • 409 Conflict: Coinbhleacht ghnó (m.sh. coinbhleacht leagan, „ní cheadaíonn stádas an gníomh seo“, sárú eochair uathúil má tá sé ábhartha go gnóthach).
  • 422 Unprocessable Content: Má tá an sintacs ceart ach teipeann ar bhailíochtú gnó (ní úsáideann gach foireann 422, ach is minic go mbíonn sé níos soiléire ná 400).
  • 500: Gach rud nach féidir leat a cheannachóiriú go soiléir. Áirítear leis sin go minic „bunachar sonraí síos“, „am-éagtha“, „Unhandled Exception“.

Cleas sonrach do Delphi: Tagann go leor earráidí DB suas mar Exceptions ghinearálta. Tá fiúntas ag an leibhéal rochtana sonraí seiceáil go sonrach ar chásanna ar eolas agus iad a thiontú go EApiError. Tábhachtach: Ná cur slis SQL ná ainmneacha tábla/colún inmheánacha isteach sa teachtaireacht chuig an gcliant. Tá na sonraí sin don log, ní don fhreagra.

Cleas Debugging: earráidí inathnuaite trí „Contract Snapshot“

Neamhghnách, ach an-úsáideach sa bhainistíocht: Sábháil i gcás earráidí (nó go beacht do IDanna Correlation áirithe) „snapshot“ de cheannteidil an iarratais + comhlacht an iarratais i gcomhad spool debug. Ní logging buan é seo (cosaint sonraí/volúim), ach uirlis rialaithe chun cásanna deacair a athchruthú ó chomhthéacs táirgthe.

Tábhachtach: Níor chóir le do thoil go gcoinneofar snapshot gan scagadh na Auth-Header, Token nó sonraí pearsanta. Sa phraiticiúlacht ciallaíonn sé sin: redaction (maisciú) agus gníomhachtú ach trí Feature-Flag nó Whitelist (m.sh. ach do IDanna Correlation sonraithe, fuinneoga ama gearra).

Cur i bhfeidhm glan sa chleachtas: maisciú in ionad eisiamh

I gcomhtháthuithe fíor, is minic gurb iad na réimsí „criticiúla“ iad a bheadh riachtanach don debug (m.sh. aitheantóirí). In áit iad a eisiamh go forleathan is fearr iad a mhasciú: cuid den Token a chur in áit, r-phost a choinneáil ach an fearann, IBAN ach na huimhreacha deireanacha. Mar sin fanann an cás inathnuaite, gan sonraí gan ghá a scaipeadh sa chóras comhad. Chomh maith leis sin, ba chóir an snapshot a shainaithint go soiléir mar ábhar debug agus tréimhse choimeád shonraithe a bheith ann.

Slándáil agus Oibriú: Seachadadh ceannlíne, Slabhraí Proxy agus Timeouts

Ní chríochnaíonn API REST de ghnáth go díreach ag an gcliant. Is gnách go mbíonn slabhraí ó Reverse Proxy, TLS-Termination, WAF nó API-Gateway. Mar thoradh air sin tá pointí praiticiúla:

  • IP iargúlta: Ná bíodh muinín iomlán agat as X-Forwarded-For. Glac é amháin ó proxies iontaofa; mura bhfuil, bain úsáid as an IP socket díreach. I lámhleabhair oibriúcháin ba chóir a bheith soiléir cé na hops atá „trusted“.
  • Timeouts: Má tá timeout 30 soicind ag an proxy ach go n-éilíonn do backend 2 nóiméad, cruthaíonn sin ghost-requests. Socraigh timeouts go comhsheasmhach trasna na slabhra agus déan cinneadh: iarratas sínchrónach nó patrún poist (Job-Pattern) (202 Accepted + deireadhphointe stádais).
  • Correlation-ID: Cuir an Correlation-ID sna Response-Header ionas gur féidir le riarthóirí é a chomhcheangal idir na logs agus taobh an chliaint. Má úsáideann gateway a Request-IDs féin: logáil agus mapáil an dá ID.
  • Teachtaireachtaí earráide: I dtimpeallacht táirgthe ná nocht sonraí inmheánacha. Nocht sonraí dífhabhtaithe amháin go rialaithe (Stage/Feature-Flag) agus, más gá, coinneáil iad sna logaí amháin.

Sainmhíniú: Cén fáth go bhféadfadh RemObjects SDK a bheith i bhfabhar anseo

I gcórais Delphi tógann a lán forbróirí freastalaithe REST-Server go minic le frámaí níos éadroime (m.sh. rótar HTTP íosta). Baintear neart as RemObjects SDK nuair atá ailtireacht ilshraithe agat cheana féin nó má theastaíonn uait é:

  • Teorainneacha Seirbhíse Soiléir: Tá modhanna seirbhíse sainmhínithe go soiléir agus is féidir conarthaí a leaganú.
  • Iompair agus Serialisierung: Is féidir leat JSON a úsáid, ach freisin formáidí teachtaireachta eile (ag brath ar an setup), gan an loighic ghnó a mheascadh.
  • Reáchtáil: Is féidir pleanáil a dhéanamh ar roghanna óstála agus ar ionchuimsithe i seirbhísí Windows- agus Linux-seirbhísí, lena n-áirítear rollouts glan.

Cuireann an cur chuige léirithe leis na codanna a bhíonn in easnamh go minic sa ghnáthshaol: réada earráide aonfhoirmeacha, leaganú diongbháilte agus logáil inar féidir comhleasú a dhéanamh. Go háirithe i mbogearraí corparáideacha saincheaptha le saolré fada, sábhálann sé seo am le linn nuashonruithe agus i gcomhtháthú córas seachtrach.

Conclúid: An fiú an iarracht — agus cá háit a thiteann an cur chuige?

Cruthaítear an luach breise nuair nach n-oibríonn do chomhéadan REST ach amháin go hiontach, ach gur féidir é a reáchtáil go buan: conarthaí JSON seasmhacha, leaganú gan pléascadh URLanna, earráidí inléite agus dífhabhtú gan gá le tuairimíocht. Is sa réimse sin a bhfuil an cur chuige le Comhthéacs, Correlation-ID agus léarscáil eisceachtaí lárnach i RemObjects SDK láidir.

Teorainneacha úsáide: Má tá deireán aonair, gearrshaol agat gan comhpháirtithe comhtháthaithe, is féidir le versionáil bunaithe ar Media-Type deamhain a dhéanamh mar overengineering. Níl logáil snapshot ciallmhar ach má chuireann tú Redaction agus gníomhachtú i bhfeidhm go disciplíneach. Agus: má dhéanann do stac proxy na header a „optamú“ nó iad a bhaint, caithfidh tú an bonneagar a chur i gceart ar dtús, murach sin beidh tú ag dífhabhtú an chiseal mícheart.

Má tá tú ag nuashonrú réimse freastalaithe Delphi atá ann cheana nó má theastaíonn uait réiteach bogearraí gar don phróiseas a chomhtháthú go glan i ERP/DMS/CRM, is minic go mbítear na meicníochtaí seo mar an difríocht idir „oibríonn sa tástáil“ agus „oibríonn sa táirgeadh“.

I gcomhthéacs ghairmiúil teicniúil imríonn Delphi REST-API agus REST-Server agus Remobjects Sdk Delphi ról tábhachtach freisin, nuair is gá go gcomhoibreoidh comhtháthú, sreafaí sonraí agus forbairt leanúnach go glan.

Pléigh tionscadal nó tionscnamh nua-aoisithe le Net-Base.

Céim eile

Nuair a éiríonn an téama ina thionscadal iarbhír, ba cheart ailtireacht, maoin reatha agus oibríocht a mheas le chéile go luath.

Ní hamháin go dtacaímid le ceisteanna aonair, ach freisin nuair is gá ó shlisíní cód foinse, ó ábhair legacy nó ó smaointe portail tionscadal corparáideach iontaofa a fhorbairt.

  • Measúnítear an staid reatha, an stát sprioc agus na rioscaí teicniúla le chéile.
  • REST, rochtain ar shonraí, portaill agus Rollout, ní chuirfear iad siar mar iarmhairtí déanacha.
  • Feicfidh sibh go luath cén bealach atá eacnamaíoch agus ó thaobh oibríochta inbhuanaithe.

Roinn an post

Roinn an t-alt seo go díreach

Tá LinkedIn, X, XING, Facebook, WhatsApp agus ríomhphost ar fáil láithreach. Maidir le Instagram, táimid ag ullmhú an nasca agus téacs gairid láithreach.

Ríomhphost

Osclaítear Instagram i gcluaisín nua. Cóipeáiltear an nasc agus an téacs gairid roimh ré isteach sa ghearrthaisce.