Service Binding, metadata, CSRF token és PATCH kérés gyakorlati szemmel
Az előző részekben bemutattam, miért érdemes egy külső alkalmazást RAP/OData alapú szolgáltatáson keresztül SAP-hoz kapcsolni, majd végigmentünk azon is, hogyan épül fel SAP oldalon a RAP objektumlánc. A fejlesztés végén azonban jön egy nagyon gyakorlati kérdés: honnan tudom pontosan, milyen URL-t kell hívnia a külső alkalmazásnak, milyen entity setek érhetők el, milyen mezőket vár a szolgáltatás, és hogyan lehet módosító kérést, például PATCH műveletet végrehajtani?
A fókusz most nem új RAP objektumok létrehozásán van, hanem az elkészült OData V4 szolgáltatás ellenőrzésén és fogyasztásának előkészítésén. Ez különösen fontos, mert egy külső alkalmazás integrációját nem szabad érzésből megírni. A pontos végpontokat, mezőneveket, kulcsokat és típusokat az SAP oldali szolgáltatásból kell kiolvasni.

Hol található a service root URL?
A külső alkalmazás számára az egyik legfontosabb adat a service root URL. Ez az az alap URL, amelyhez képest az entity seteket, a metadata dokumentumot és a konkrét rekordokra mutató URL-eket hívjuk. Ezt nem érdemes kézzel összerakni. A helyes kiindulópont az Eclipse/ADT Service Binding objektum. Itt látható, melyik service definition van publikálva, milyen binding típussal, és milyen URL-en érhető el a szolgáltatás.
Egyszerűsített forma:
https://<host>:<port>/sap/opu/odata4/.../<service>/0001/
A fontos tanulság: a külső alkalmazás nem a CDS view nevét, nem a behavior nevét és nem az adatbázistábla nevét hívja. A külső alkalmazás a publikált OData szolgáltatás service root URL-jéből indul. Ha ez az URL hibás, akkor minden más is hibás lesz: a GET, a metadata lekérés, a CSRF token kérés és a PATCH művelet is.
Honnan tudom, mi az entity set neve?
A következő gyakori félreértés az entity set neve. Sokan ilyenkor a projection CDS vagy az interface CDS nevét próbálják meghívni. Ez rossz irány. A külső fogyasztó szempontjából az számít, hogy a service definitionben mit tettünk ki expose néven.
Például:
define service ZUI_AOT_IF_USER_O4 {
expose ZC_AOT_IF_USER as Users;
}
Ebben az esetben a külső alkalmazás számára az entity set neve:
Users
Tehát egy egyszerű GET kérés így nézhet ki:
GET <service-root>/Users
A metadata elérése pedig:
GET <service-root>/$metadata
Ez nagyon fontos különbség. A külső alkalmazásnak nem belső SAP objektumneveket kell ismernie, hanem a publikált szolgáltatási szerződést.
Mire való az /IWFND/V4_ADMIN?
Az /IWFND/V4_ADMIN az OData V4 szolgáltatások SAP Gateway oldali adminisztrációs felülete. Itt ellenőrizhető, hogy a service group publikálva van-e, elérhető-e a szolgáltatás, és innen tesztelhető is az adott OData V4 endpoint. A projekt során ez kulcslépés volt, mert az ADT-ben elkészített service binding önmagában még nem jelentette azt, hogy a külső alkalmazás már biztosan fogyasztani tudja a szolgáltatást. A Gateway oldali publikálásnak is rendben kellett lennie.
Amit itt érdemes ellenőrizni:
- látszik-e a service group;
- publikált állapotban van-e;
- elindítható-e a service test;
- működik-e egy egyszerű GET kérés;
- elérhető-e a metadata.
Ha ezek SAP oldalon sem működnek, akkor nincs értelme a C# kliensben, Postmanben vagy bármilyen külső alkalmazásban keresni a hibát. Először az SAP oldali publikálást kell rendbe tenni. Ahhoz, hogy a service testet elérjük, meg kell keressük a publikált endpointunkat és rákattintani a Service Test fülre, ezután megnyílik a teszt felület, amelyen dolgozni tudunk.

A metadata szerepe
A $metadata az OData szolgáltatás egyik legfontosabb része. Ez írja le, milyen entity setek érhetők el, milyen mezők vannak, melyek a kulcsmezők, milyen típusokat vár a szolgáltatás, és milyen formában kell a külső alkalmazásnak kommunikálnia az SAP-val. Ezért a külső alkalmazást nem a saját feltételezéseinkhez kell igazítani, hanem a metadata dokumentumhoz.
Példa:
GET <service-root>/$metadata
A metadata alapján derül ki például:
- mi az entity set pontos neve;
- melyik mező a kulcs;
- milyen mezők léteznek;
- mi a mezők pontos neve;
- milyen adattípust vár az SAP;
- mely mezők módosíthatók;
- vannak-e navigációs kapcsolatok vagy ETag információk.
Ez különösen POST vagy PATCH kérésnél fontos. Ha a metadata szerint egy mező neve IsActive, akkor a payloadban is ezt kell használni. Ha a metadata szerint egy mező stringként van publikálva, akkor nem küldhetjük úgy, mintha boolean lenne. A metadata tehát nem mellékes technikai fájl. Ez a szerződés a szolgáltatás és a külső alkalmazás között.
Mi az X-CSRF-Token?
A CSRF token módosító HTTP műveleteknél fontos. Ilyen például a POST, PATCH, PUT vagy DELETE. A lényege egyszerű: a kliensnek először kérnie kell egy tokent, majd ezt a tokent vissza kell küldenie a módosító kérés headerében.
Tipikus tokenlekérés:
GET <service-root>/
Headerben pedig:
Accept: application/json
X-CSRF-Token: Fetch
A válaszban az SAP visszaadja a tokent:
X-CSRF-Token: <token-érték>
A módosító kérésnél ezt vissza kell küldeni a headerben:
X-CSRF-Token: <token-érték>
A kritikus rész az, hogy nem csak a tokent kell megtartani, hanem az SAP által visszaadott session cookie-kat is. Ha a token egy sessionhöz tartozik, de a PATCH kérés már másik sessionnel megy ki, akkor a kérés hibázhat. Ez az egyik tipikus oka annak, hogy SAP Gateway Clientben működik egy módosítás, de külső alkalmazásból nem.
Milyen headerek fontosak?
GET kérésnél általában elég az Accept header:
Accept: application/json
Token lekérésnél:
Accept: application/json
X-CSRF-Token: Fetch
PATCH kérésnél már ezekre kell figyelni:
Content-Type: application/json
Accept: application/json
X-CSRF-Token: <token-érték>
Cookie: <SAP által visszaadott session cookie>
Bizonyos esetekben szükség lehet If-Match headerre is, például ETag vagy concurrency kezelés esetén:
If-Match: *
Ezt viszont nem szabad vakon használni. Mindig a szolgáltatás metadata dokumentuma és a GET válasz alapján kell eldönteni, hogy szükséges-e. A header nem dekoráció. A header az integrációs szerződés része.
PATCH kérés végrehajtása
A PATCH célja egy meglévő rekord részleges módosítása. Ehhez először tudni kell a rekord pontos URL-jét. Ez a service rootból, az entity set nevéből és a kulcsmezőből épül fel.
Egyszerűsített példa:
PATCH <service-root>/Users('<UserId>')
A pontos kulcsformát mindig a $metadata alapján kell ellenőrizni. Ha több kulcsmező van, vagy névvel megadott kulcsformát vár a szolgáltatás, akkor az URL is másképp nézhet ki.
Példa PATCH headerre:
Content-Type: application/json
Accept: application/json
X-CSRF-Token: <token-érték>
Cookie: <session-cookie>
Példa bodyra:
{
"IsActive": false
}
Ez csak akkor helyes, ha a metadata szerint az IsActive valóban ilyen néven és ilyen típussal módosítható mezőként szerepel. Ha a szolgáltatás más típust vár, akkor a payloadot ahhoz kell igazítani.
PATCH esetén három dolgot mindig ellenőrizni kell:
- létező mezőt küldök-e;
- módosítható mezőt küldök-e;
- olyan típust küldök-e, amit a metadata alapján a szolgáltatás vár.
Ha ezek közül bármelyik hibás, akkor nem az SAP „rossz”, hanem a kliens nem tartja be a szolgáltatási szerződést.
Tanulság
Az OData V4 szolgáltatás használata nem ott kezdődik, hogy a külső alkalmazásból elküldünk egy HTTP kérést. Először meg kell találni a pontos service root URL-t a Service Bindingban. Meg kell nézni, hogy a service definition milyen entity set néven publikálta az objektumot. Ellenőrizni kell az /IWFND/V4_ADMIN felületen, hogy a service group publikált és tesztelhető. GET kéréssel bizonyítani kell, hogy a szolgáltatás elérhető. A metadata alapján meg kell érteni a kulcsokat, mezőket és típusokat. Csak ezután érdemes módosító műveletekkel, például PATCH kéréssel dolgozni.
A legfontosabb tanulság számomra az volt, hogy a külső alkalmazást nem a saját feltételezéseimhez, hanem a metadata által leírt szerződéshez kell igazítani. Ha ezt betartjuk, az SAP-integráció sokkal kiszámíthatóbb lesz. Nem találgatunk, hanem ellenőrzött szolgáltatási szerződés alapján dolgozunk.




