AEM GraphQL API för användning med innehållsfragment graphql-api-for-use-with-content-fragments
Lär dig hur du använder innehållsfragment i Adobe Experience Manager (AEM) med AEM GraphQL API för leverans av headless-innehåll.
AEM GraphQL API som används med innehållsfragment är till stor del baserat på GraphQL-API:t med öppen källkod.
Genom att använda GraphQL API i AEM kan du effektivt leverera innehållsfragment till JavaScript-klienter i headless CMS-implementeringar:
- Undvika iterativa API-begäranden som REST,
- se till att leveransen begränsas till de specifika kraven,
- Det går att skicka exakt det som behövs för återgivningen som svar på en enda API-fråga.
- AEM Commerce använder data från en Commerce-plattform via GraphQL.
- AEM Content Fragments fungerar tillsammans med det AEM GraphQL-API:t (en anpassad implementering som baseras på standard-GraphQL) för att leverera strukturerat innehåll som kan användas i dina program.
Förutsättningar prerequisites
Kunder som använder GraphQL bör installera AEM Content Fragment med GraphQL Index Package 1.0.5. Se Versionsinformation för mer information.
GRAPHQL API graphql-api
GraphQL är:
-
"…ett frågespråk för API:er och en körningsmiljö för att utföra dessa frågor med dina befintliga data. GraphQL ger en fullständig och begriplig beskrivning av data i ditt API. Det ger kunderna möjlighet att fråga efter exakt vad de behöver och ingenting mer, gör det enklare att utveckla API:er över tid och möjliggör kraftfulla utvecklingsverktyg.".
Se GraphQL.org
-
"…en öppen specifikation för ett flexibelt API-lager. Placera GraphQL över era befintliga backend-system så att ni kan skapa produkter snabbare än någonsin …".
Se Utforska GraphQL.
-
"… ett språk och en specifikation för datafrågor som utvecklats internt av Facebook under 2012 innan man började använda öppen källkod 2015. Det är ett alternativ till REST-baserade arkitekturer i syfte att öka utvecklarnas produktivitet och minimera mängden data som överförs. GraphQL används i produktionen av hundratals organisationer av alla storlekar…"
Mer information om GraphQL API finns i följande avsnitt (bland annat):
Implementeringen av GraphQL för AEM baseras på GraphQL Java™-standardbibliotek. Se:
GraphQL Terminologi graphql-terminology
GraphQL använder följande:
-
- Scheman genereras av AEM baserat på modeller för innehållsfragment.
- Med hjälp av dina scheman kan GraphQL presentera de typer och åtgärder som är tillåtna för implementeringen av GraphQL AEM.
-
-
Sökvägen i AEM som svarar på GraphQL-frågor och ger åtkomst till GraphQL-scheman.
-
Se Aktivera din GraphQL-slutpunkt för mer information.
-
Se (GraphQL.org) Introduktion till GraphQL för utförlig information, inklusive Bästa praxis.
GraphQL Query Types graphql-query-types
Med GraphQL kan du utföra frågor för att returnera:
-
A enkel post
AEM innehåller funktioner för att konvertera frågor (båda typerna) till Beständiga frågor som cachas av Dispatcher och CDN.
GraphQL Query Best Practices (Dispatcher and CDN) graphql-query-best-practices
Beständiga frågor är den rekommenderade metod som ska användas för publiceringsinstanser som:
- de är cachelagrade
- de hanteras centralt av AEM
GraphQL-frågor som använder förfrågningar om POST rekommenderas inte eftersom de inte cachelagras, så i en standardinstans är Dispatcher konfigurerad att blockera sådana frågor.
Även om GraphQL har stöd för GET-förfrågningar kan dessa förfrågningar få en träffgräns (till exempel längden på URL:en) som kan undvikas med beständiga frågor.
Se Aktivera cachelagring av beständiga frågor för mer information.
GraphiQL-gränssnitt graphiql-interface
En implementering av standarden GraphiQL -gränssnittet kan användas med AEM GraphQL.
Med det här gränssnittet kan du direkt mata in och testa frågor.
Till exempel:
http://localhost:4502/content/graphiql.html
Den innehåller funktioner som syntaxmarkering, automatisk komplettering, autoföreslå, samt historik och onlinedokumentation:
Användningsexempel för skribent- och publiceringsmiljöer use-cases-author-publish-environments
Användningsexemplen kan bero på vilken typ av AEM som används:
-
Publiceringsmiljö; används för att:
- Frågedata för JS-program (standardfall)
-
Författarmiljö, används för att:
-
Fråga efter data för"innehållshanteringssyften":
- GraphQL i AEM är ett skrivskyddat API.
- REST API kan användas för CR(u)D-åtgärder.
-
Behörigheter permission
Behörigheterna krävs för åtkomst av resurser.
GraphQL-frågor körs med tillstånd från den AEM användaren av den underliggande begäran. Om användaren inte har läsåtkomst till vissa fragment (som lagras som resurser) blir de inte en del av resultatuppsättningen.
Användaren måste också ha tillgång till en GraphQL-slutpunkt för att kunna köra GraphQL-frågor.
Schemagenerering schema-generation
GraphQL är ett typbestämt API, vilket innebär att data måste vara tydligt strukturerade och ordnade efter typ.
GraphQL-specifikationen innehåller en serie riktlinjer för hur du skapar ett robust API för att förhöra data i en viss instans. Kunden måste hämta Schema, som innehåller alla typer som behövs för en fråga.
För innehållsfragment baseras GraphQL-scheman (struktur och typer) på Aktiverad Modeller för innehållsfragment och deras datatyper.
Om en användare till exempel har skapat en innehållsfragmentmodell som kallas Article
AEM sedan generera en GraphQL-typ ArticleModel
. Fälten i den här typen motsvarar fälten och datatyperna som definieras i modellen. Dessutom skapas vissa startpunkter för frågor som arbetar med den här typen, till exempel articleByPath
eller articleList
.
-
En innehållsfragmentmodell:
-
Motsvarande GraphQL-schema (utdata från den automatiska dokumentationen för GraphiQL):
Den här bilden visar att den genererade typen
ArticleModel
innehåller flera fält.-
Tre av dem har kontrollerats av användaren:
author
,main
ochreferencearticle
. -
De andra fälten lades till automatiskt av AEM och representerar användbara metoder för att tillhandahålla information om ett visst innehållsfragment. I detta exempel hjälpfält)
_path
,_metadata
,_variations
.
-
-
När en användare har skapat ett innehållsfragment baserat på artikelmodellen kan det sedan förhöras via GraphQL. Mer information finns i Exempelfrågor (baserat på exempelstruktur för innehållsfragment för användning med GraphQL).
I GraphQL for AEM är schemat flexibelt. Denna flexibilitet innebär att den genereras automatiskt varje gång en innehållsfragmentmodell skapas, uppdateras eller tas bort. Cacheminnen för dataschemat uppdateras också när du uppdaterar en innehållsfragmentmodell.
Tjänsten Sites GraphQL avlyssnar (i bakgrunden) alla ändringar som görs i en innehållsfragmentmodell. När uppdateringar upptäcks återskapas endast den delen av schemat. Denna optimering sparar tid och ger stabilitet.
Om du till exempel:
-
Installera ett paket som innehåller
Content-Fragment-Model-1
ochContent-Fragment-Model-2
:- GraphQL-typer för
Model-1
ochModel-2
genereras.
- GraphQL-typer för
-
Ändra sedan
Content-Fragment-Model-2
:-
Endast
Model-2
GraphQL-typsnitt uppdateras. -
med beaktande av följande:
Model-1
förblir detsamma.
-
Schemat hanteras via samma slutpunkt som GraphQL-frågorna, där klienthanteraren hanterar det faktum att schemat anropas med tillägget GQLschema
. Du kan till exempel utföra en enkel GET
begäran på /content/cq:graphql/global/endpoint.GQLschema
resulterar i utdata från schemat med innehållstypen: text/x-graphql-schema;charset=iso-8859-1
.
Schemagenerering - opublicerade modeller schema-generation-unpublished-models
När innehållsfragment är kapslade kan det hända att en överordnad Content Fragment Model publiceras, men ingen refererad modell gör det.
När det inträffar genererar AEM en ofullständig Schema för den överordnade innehållsfragmentmodellen. Det innebär att fragmentreferensen, som är beroende av den opublicerade modellen, tas bort från schemat.
Fält fields
Inom schemat finns det enskilda fält av två baskategorier:
-
Fält som du genererar.
Ett urval av Datatyper används för att skapa fält baserat på hur du konfigurerar innehållsfragmentmodellen. Fältnamnen hämtas från Egenskapsnamn fält för Datatyp.
- Det finns också Återge som inställningar som ska beaktas, eftersom användare kan konfigurera vissa datatyper. Ett textfält med en rad kan till exempel konfigureras att innehålla flera enkelradiga texter genom att välja
multifield
i listrutan.
- Det finns också Återge som inställningar som ska beaktas, eftersom användare kan konfigurera vissa datatyper. Ett textfält med en rad kan till exempel konfigureras att innehålla flera enkelradiga texter genom att välja
-
GraphQL för AEM genererar också flera hjälpfält.
Dessa fält används för att identifiera ett innehållsfragment eller för att få mer information om ett innehållsfragment.
Datatyper data-types
GraphQL för AEM har stöd för en lista med typer. Alla Content Fragment Model-datatyper som stöds och motsvarande GraphQL-typer visas:
String
, [String]
String
Float
, [Float]
Boolean
Calendar
onlyDate
, onlyTime
, dateTime
String
[String]
String
Ett fält:
Model
- Modelltyp, refereras direktMultifält, med en referenstyp:
[Model]
- Array av typen Model
, som refereras direkt från en arrayMultifält, med flera refererade typer:
[AllFragmentModels]
- Array med alla modelltyper, refererad från array med unionstypHjälpfält helper-fields
Förutom datatyperna för användargenererade fält genererar GraphQL för AEM även flera hjälpare fält som hjälper dig att identifiera ett innehållsfragment eller att ge mer information om ett innehållsfragment.
Dessa hjälpfält markeras med föregående _
för att skilja mellan vad som har definierats av användaren och vad som har genererats automatiskt.
Bana path
Sökvägsfältet används som en identifierare i AEM GraphQL. Den representerar sökvägen till Content Fragment-resursen i AEM. Den här sökvägen väljs som identifierare för ett innehållsfragment eftersom den:
- är unikt inom AEM,
- kan enkelt hämtas.
I följande kod visas sökvägarna för alla innehållsfragment som har skapats baserat på modellen för innehållsfragment Person
.
{
personList {
items {
_path
}
}
}
Om du vill hämta ett enstaka innehållsfragment av en viss typ måste du också bestämma sökvägen först. Till exempel:
{
authorByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
firstName
name
}
}
}
Se Exempelfråga - Ett enskilt specifikt stadsfragment.
Metadata metadata
Via GraphQL visar AEM också metadata för ett innehållsfragment. Metadata är den information som beskriver ett innehållsfragment, till exempel följande:
- titeln på ett innehållsfragment
- miniatyrbildssökvägen
- beskrivningen av ett innehållsfragment
- och det datum då den skapades, bland annat.
Eftersom metadata genereras via Schemaredigeraren och därför inte har någon särskild struktur, har TypedMetaData
GraphQL-typ implementerades för att visa metadata för ett innehållsfragment. The TypedMetaData
visar informationen som grupperats med följande skalära typer:
stringMetadata:[StringMetadata]!
stringArrayMetadata:[StringArrayMetadata]!
intMetadata:[IntMetadata]!
intArrayMetadata:[IntArrayMetadata]!
floatMetadata:[FloatMetadata]!
floatArrayMetadata:[FloatArrayMetadata]!
booleanMetadata:[BooleanMetadata]!
booleanArrayMetadata:[booleanArrayMetadata]!
calendarMetadata:[CalendarMetadata]!
calendarArrayMetadata:[CalendarArrayMetadata]!
Varje skalär typ representerar antingen ett namn/värde-par eller en array med namn/värde-par, där värdet för det paret är av den typ som det grupperades i.
Om du till exempel vill hämta titeln för ett innehållsfragment är den här egenskapen en String-egenskap, så du vill fråga efter alla strängmetadata:
Så här frågar du efter metadata:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_path
_metadata {
stringMetadata {
name
value
}
}
}
}
}
Du kan visa alla metadata för GraphQL-typer om du visar det genererade GraphQL-schemat. Alla modelltyper har samma TypedMetaData
.
Kom ihåg att
StringMetadata
och StringArrayMetadata
båda hänvisar till vad som lagras i databasen, inte till hur du hämtar dem.stringMetadata
får du en array med alla metadata som lagras i databasen som String
. Och om du ringer stringArrayMetadata
får du en array med alla metadata som lagras i databasen som String[]
.Se Exempelfråga för metadata - Ange metadata för utmärkelserna med namnet GB.
Variationer variations
The _variations
-fältet har implementerats för att förenkla frågor om variationer som ett innehållsfragment har. Till exempel:
{
personByPath(_path: "/content/dam/path/to/fragment/john-doe") {
item {
_variations
}
}
}
_variations
fältet innehåller inte master
variation, som tekniskt sett originaldata (refereras som Master i användargränssnittet) inte betraktas som en explicit variation.Se Exempelfråga - Alla städer med en namngiven variant.
GraphQL Variables graphql-variables
GraphQL tillåter att variabler placeras i frågan. Mer information finns i GraphQL-dokumentation för variabler.
Om du till exempel vill hämta alla innehållsfragment av typen Article
som har en viss variant kan du ange variabeln variation
i GraphiQL.
### query
query GetArticlesByVariation($variation: String!) {
articleList(variation: $variation) {
items {
_path
author
_variations
}
}
}
### in query variables
{
"variation": "uk"
}
GraphQL Direktiv graphql-directives
I GraphQL finns det en möjlighet att ändra frågan baserat på variabler, så kallade GraphQL-direktiv.
Här kan du till exempel inkludera adventurePrice
fält i en fråga för alla AdventureModels
, baserat på en variabel includePrice
.
### query
query GetAdventureByType($includePrice: Boolean!) {
adventureList {
items {
adventureTitle
adventurePrice @include(if: $includePrice)
}
}
}
### in query variables
{
"includePrice": true
}
Filtrering filtering
Du kan också använda filtrering i dina GraphQL-frågor för att returnera specifika data.
Vid filtrering används en syntax som baseras på logiska operatorer och uttryck.
Den mest atomiska delen är ett enstaka uttryck som kan tillämpas på innehållet i ett visst fält. Innehållet i fältet jämförs med ett givet konstantvärde.
Följande uttryck skulle till exempel jämföra innehållet i fältet med värdet some text
och lyckas om innehållet är lika med värdet. Annars misslyckas uttrycket:
{
value: "some text"
_op: EQUALS
}
Följande operatorer kan användas för att jämföra fält med ett visst värde:
EQUALS
String
, ID
, Boolean
EQUALS_NOT
String
, ID
CONTAINS
String
{ value: "mas", _op: CONTAINS }
matchar Christmas
, Xmas
, master
, …)CONTAINS_NOT
String
STARTS_WITH
ID
{ value: "/content/dam/", _op: STARTS_WITH
matchar /content/dam/path/to/fragment
, men inte /namespace/content/dam/something
EQUAL
Int
, Float
UNEQUAL
Int
, Float
GREATER
Int
, Float
GREATER_EQUAL
Int
, Float
LOWER
Int
, Float
LOWER_EQUAL
Int
, Float
AT
Calendar
, Date
, Time
NOT_AT
Calendar
, Date
, Time
BEFORE
Calendar
, Date
, Time
AT_OR_BEFORE
Calendar
, Date
, Time
AFTER
Calendar
, Date
, Time
AT_OR_AFTER
Calendar
, Date
, Time
I vissa typer kan du även ange ytterligare alternativ som ändrar hur ett uttryck utvärderas:
_ignoreCase
String
time
matchar TIME
, time
, tImE
, …_sensitiveness
Float
float
värden som ska anses vara desamma (för att kringgå tekniska begränsningar på grund av den interna representationen av float
värden; bör undvikas eftersom detta alternativ kan ha en negativ inverkan på prestandanUttryck kan kombineras till en uppsättning med hjälp av en logisk operator (_logOp
):
OR
- uttrycksuppsättningen lyckas om minst ett uttryck lyckasAND
- uttrycksuppsättningen lyckas om alla uttryck lyckas (standard)
Varje fält kan filtreras med en egen uppsättning uttryck. Uttrycksuppsättningarna för alla fält som omnämns i filterargumentet kombineras till slut av den egna logiska operatorn.
En filterdefinition (skickas som filter
argument till en fråga) innehåller:
- En underdefinition för varje fält (fältet kan nås via namnet, till exempel finns det en
lastName
i filtret förlastName
i fältet Data (fälttyp) - Varje underdefinition innehåller
_expressions
-array, som innehåller uttrycksuppsättningen och_logOp
fält som definierar den logiska operatorn ska uttrycken kombineras med - Varje uttryck definieras av värdet (
value
fält) och operatorn (_operator
fält) innehållet i ett fält ska jämföras med
Du kan utesluta _logOp
om du vill kombinera objekt med AND
och _operator
om du vill kontrollera om de är lika, eftersom dessa värden är standardvärden.
I följande exempel visas en fullständig fråga som filtrerar alla personer som har en lastName
av Provo
eller innehåller sjö
, oberoende av omständigheterna:
{
authorList(filter: {
lastname: {
_logOp: OR
_expressions: [
{
value: "sjö",
_operator: CONTAINS,
_ignoreCase: true
},
{
value: "Provo"
}
]
}
}) {
items {
lastName
firstName
}
}
}
När en GraphQL-fråga körs med valfria variabler, om ett specifikt värde är not som anges för den valfria variabeln ignoreras variabeln i filterutvärderingen. Det innebär att frågeresultaten innehåller alla värden, båda null
och inte null
, för egenskapen som är relaterad till filtervariabeln.
null
värdet är explicit som anges för en sådan variabel, kommer filtret endast att matcha null
värden för motsvarande egenskap.I frågan nedan, där inget värde har angetts för egenskapen lastName
:
query getAuthorsFilteredByLastName($authorLastName: String) {
authorList(filter:
{
lastName: {_expressions: {value: $authorLastName}
}}) {
items {
lastName
}
}
}
Alla författare returneras:
{
"data": {
"authorList": {
"items": [
{
"lastName": "Hammer"
},
{
"lastName": "Provo"
},
{
"lastName": "Wester"
},
{
"lastName": null
},
...
]
}
}
}
Du kan även filtrera efter kapslade fält, men det rekommenderas inte eftersom det kan leda till prestandaproblem.
Ytterligare exempel finns i:
-
information om GraphQL for AEM extensions
-
Exempelfrågor med detta exempelinnehåll och -struktur
- Och Exempelinnehåll och struktur förberedda för användning i provfrågor
Sortering sorting
Med den här funktionen kan du sortera frågeresultaten enligt ett angivet fält.
Sorteringskriterierna:
-
är en kommaavgränsad lista med värden som representerar fältsökvägen
-
det första fältet i listan definierar den primära sorteringsordningen
- det andra fältet används om två värden för det primära sorteringsvillkoret är lika
- det tredje fältet används om de första två kriterierna är lika, och så vidare.
-
punktnotation, d.v.s.
field1.subfield.subfield
och så vidare.
-
-
med valfri orderriktning
- ASC (stigande) eller DESC (fallande); som standard används ASC
- riktningen kan anges per fält. Det innebär att du kan sortera ett fält i stigande ordning och ett annat i fallande ordning (namn, firstName DESC)
Till exempel:
query {
authorList(sort: "lastName, firstName") {
items {
firstName
lastName
}
}
}
Och dessutom:
{
authorList(sort: "lastName DESC, firstName DESC") {
items {
lastName
firstName
}
}
}
Du kan även sortera ett fält i ett kapslat fragment med formatet nestedFragmentname.fieldname
.
Till exempel:
query {
articleList(sort: "authorFragment.lastName") {
items {
title
authorFragment {
firstName
lastName
birthDay
}
slug
}
}
}
Sidindelning paging
Med den här funktionen kan du utföra sidindelning på frågetyper som returnerar en lista. Det finns två metoder:
offset
ochlimit
i enList
frågafirst
ochafter
i enPaginated
fråga
Listfråga - förskjutning och begränsning list-offset-limit
I en ...List
fråga som du kan använda offset
och limit
om du vill returnera en viss delmängd av resultaten:
offset
: Anger den första datauppsättningen som ska returneraslimit
: Anger maximalt antal datauppsättningar som ska returneras
Om du till exempel vill visa en resultatsida som innehåller upp till fem artiklar, med början från den femte artikeln från complete resultatlista:
query {
articleList(offset: 5, limit: 5) {
items {
authorFragment {
lastName
firstName
}
}
}
}
-
Sidindelning kräver en stabil sorteringsordning för att fungera korrekt i flera frågor som begär olika sidor i samma resultatuppsättning. Som standard används databassökvägen för varje objekt i resultatuppsättningen för att säkerställa att ordningen alltid är densamma. Om en annan sorteringsordning används, och om sorteringen inte kan göras på JCR-frågenivå, så har resultatet en negativ effekt. Orsaken är att hela resultatuppsättningen måste läsas in i minnet innan sidorna bestäms.
-
Ju högre förskjutning, desto längre tid tar det att hoppa över objekten från den fullständiga JCR-frågeresultatuppsättningen. En alternativ lösning för stora resultatuppsättningar är att använda den numrerade frågan med
first
ochafter
-metod.
Sidnumrerad fråga - första och efter paginated-first-after
The ...Paginated
frågetypen återanvänder de flesta ...List
frågetypsfunktioner (filtrering, sortering), men i stället för att använda offset
/limit
argument, använder first
/after
argument som definieras av GraphQL Cursor Connections Specification. Du hittar en mindre formell introduktion i GraphQL introduktion.
first
:n
första objekt som ska returneras.
Standardvärdet är50
.
Maxvärdet är100
.after
: Markören som bestämmer början på den begärda sidan. Det objekt som markören representerar tas inte med i resultatuppsättningen. Markören för ett objekt bestäms avcursor
fält föredges
struktur.
Du kan till exempel skriva ut en resultatsida som innehåller upp till fem äventyr, med början från markörobjektet i complete resultatlista:
query {
adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
edges {
cursor
node {
title
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
-
Som standard används UUID för databasnoden som representerar fragmentet för att säkerställa att resultatordningen alltid är densamma. När
sort
används UUID implicit för att säkerställa en unik sortering, även för två objekt med identiska sorteringsnycklar. -
På grund av interna tekniska begränsningar försämras prestanda om sortering och filtrering används i kapslade fält. Använd därför filter-/sorteringsfält som lagras på rotnivå. Den här tekniken rekommenderas också om du vill fråga efter stora sidnumrerade resultatuppsättningar.
GraphQL Persistent Queries - aktivera cachelagring i Dispatcher graphql-persisted-queries-enabling-caching-dispatcher
Cachelagring av beständiga frågor är inte aktiverat som standard i Dispatcher. Standardaktivering är inte möjlig eftersom kunder som använder CORS (Cross-Origin Resource Sharing) med flera ursprung måste granska och eventuellt uppdatera sin Dispatcher-konfiguration.
Vary
header.Aktivera cachelagring av beständiga frågor enable-caching-persisted-queries
För att aktivera cachelagring av beständiga frågor krävs följande uppdateringar av Dispatcher-konfigurationsfilerna:
-
<conf.d/rewrites/base_rewrite.rules>
code language-xml # Allow the dispatcher to be able to cache persisted queries - they need an extension for the cache file RewriteCond %{REQUEST_URI} ^/graphql/execute.json RewriteRule ^/(.*)$ /$1;.json [PT]
note note NOTE Dispatcher lägger till suffixet .json
till alla beständiga fråge-URL:er, så att resultatet kan cachelagras.Detta är för att säkerställa att frågan uppfyller Dispatcher-kraven för dokument som kan cachas. Mer information finns i Hur returnerar Dispatcher dokument? -
<conf.dispatcher.d/filters/ams_publish_filters.any>
code language-xml # Allow GraphQL Persisted Queries & preflight requests /0110 { /type "allow" /method '(GET|POST|OPTIONS)' /url "/graphql/execute.json*" }
CORS-konfiguration i Dispatcher cors-configuration-in-dispatcher
Kunder som använder CORS-begäranden kan behöva granska och uppdatera sin CORS-konfiguration i Dispatcher.
-
The
Origin
får inte skickas till AEM publicera via Dispatcher:- Kontrollera
clientheaders.any
-fil.
- Kontrollera
-
CORS-begäranden måste i stället utvärderas för tillåtna ursprung på Dispatcher-nivå. På så sätt säkerställs också att CORS-relaterade rubriker ställs in korrekt, på ett och samma ställe, i samtliga fall.
- En sådan konfiguration bör läggas till i
vhost
-fil. En exempelkonfiguration ges nedan. För enkelhetens skull har endast den korrespondensrelaterade delen angetts. Du kan anpassa den efter dina specifika användningsexempel.
code language-xml <VirtualHost *:80> ServerName "publish" # ... <IfModule mod_headers.c> Header add X-Vhost "publish" ################## Start of the CORS specific configuration ################## SetEnvIfExpr "req_novary('Origin') == ''" CORSType=none CORSProcessing=false SetEnvIfExpr "req_novary('Origin') != ''" CORSType=cors CORSProcessing=true CORSTrusted=false SetEnvIfExpr "req_novary('Access-Control-Request-Method') == '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=invalidpreflight CORSProcessing=false SetEnvIfExpr "req_novary('Access-Control-Request-Method') != '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != '' " CORSType=preflight CORSProcessing=true CORSTrusted=false SetEnvIfExpr "req_novary('Origin') -strcmatch 'https://%{HTTP_HOST}*'" CORSType=samedomain CORSProcessing=false # For requests that require CORS processing, check if the Origin can be trusted SetEnvIfExpr "%{HTTP_HOST} =~ /(.*)/ " ParsedHost=$1 ################## Adapt the regex to match CORS origin for your environment SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(https://.*.your-domain.tld(:\d+)?$)#" CORSTrusted=true # Extract the Origin header SetEnvIfNoCase ^Origin$ ^https://(.*)$ CORSTrustedOrigin=https://$1 # Flush If already set Header unset Access-Control-Allow-Origin Header unset Access-Control-Allow-Credentials # Trusted Header always set Access-Control-Allow-Credentials "true" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Origin "%{CORSTrustedOrigin}e" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Methods "GET" "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Max-Age 1800 "expr=reqenv('CORSTrusted') == 'true'" Header always set Access-Control-Allow-Headers "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers" "expr=reqenv('CORSTrusted') == 'true'" # Non-CORS or Not Trusted Header unset Access-Control-Allow-Credentials "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Allow-Origin "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Allow-Methods "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" Header unset Access-Control-Max-Age "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'" # Always vary on origin, even if its not there. Header merge Vary Origin # CORS - send 204 for CORS requests which are not trusted RewriteCond expr "reqenv('CORSProcessing') == 'true' && reqenv('CORSTrusted') == 'false'" RewriteRule "^(.*)" - [R=204,L] ################## End of the CORS specific configuration ################## </IfModule> <Directory /> # ... </Directory> # ... </VirtualHost>
- En sådan konfiguration bör läggas till i
GraphQL for AEM - i korthet graphql-extensions
Den grundläggande funktionen för frågor med GraphQL för AEM följer GraphQL standardspecifikation. Det finns några tillägg för GraphQL-frågor med AEM:
-
Om du behöver ett enda resultat:
- använd modellnamnet, till exempel ort
-
Om du förväntar dig en resultatlista:
- lägg till
List
till modellnamnet, till exempelcityList
- Se Exempelfråga - All information om alla städer
Då kan du:
-
ASC
: stigandeDESC
: fallande
-
Returnera en resultatsida med antingen:
- lägg till
-
Filtret
includeVariations
ingår iList
frågetyp. Om du vill hämta variationer för innehållsfragment i frågeresultaten,includeVariations
filter måste anges tilltrue
.note caution CAUTION Filtret includeVariations
kan inte användas tillsammans med det systemgenererade fältet_variation
. -
Om du vill använda ett logiskt OR:
- use
_logOp: OR
- Se Exempelfråga - Alla personer som har namnet "Jobs" eller "Smith"
- use
-
Logiskt AND finns också, men är (ofta) implicit
-
Du kan fråga efter fältnamn som motsvarar fälten i innehållsfragmentmodellen
-
Förutom fälten från modellen finns det vissa systemgenererade fält (föregås av understreck):
-
För innehåll:
-
_locale
: för att visa språket, baserat på Språkhanteraren -
_metadata
: för att visa metadata för ditt fragment -
_model
: tillåt frågor för en innehållsfragmentmodell (sökväg och rubrik) -
_path
: sökvägen till ditt innehållsfragment i databasen -
_reference
: för att visa referenser, inklusive textbundna referenser i RTF-redigeraren -
_variation
: för att visa specifika variationer i ditt innehållsfragmentnote note NOTE Om den angivna variationen inte finns för ett innehållsfragment returneras huvudvarianten som ett (fallback) standardvärde. note caution CAUTION Det systemgenererade fältet _variation
kan inte användas tillsammans med filtretincludeVariations
. -
_tags
: för att visa ID:n för innehållsfragment eller variationer som innehåller taggar; den här listan är en array medcq:tags
identifierare.- Se Exempelfråga - namn på alla städer som taggats som stadbrytningar
- Se Exempelfråga för innehållsfragmentvariationer för en viss modell som har en specifik tagg bifogad
note note NOTE Taggar kan också efterfrågas genom att en lista med metadata för ett innehållsfragment visas.
-
-
Och åtgärder:
-
_operator
: tillämpa särskilda operatörer,EQUALS
,EQUALS_NOT
,GREATER_EQUAL
,LOWER
,CONTAINS
,STARTS_WITH
-
_apply
: att tillämpa särskilda villkor, till exempelAT_LEAST_ONCE
-
_ignoreCase
: att ignorera skiftläget vid fråga
-
-
-
GraphQL-unionstyper stöds:
-
Reservation vid fråga om kapslade fragment:
- Om den begärda varianten inte finns i ett kapslat fragment, kommer Master variationen returneras.
CORS-filter cors-filter
Konfigurera en CORS-princip i kundens Git-databas för att få åtkomst till GraphQL-slutpunkten. Den här konfigurationen görs genom att en lämplig OSGi CORS-konfigurationsfil läggs till för en eller flera önskade slutpunkter.
Den här konfigurationen måste ange en betrodd webbplatsens ursprung alloworigin
eller alloworiginregexp
för vilka tillträde måste beviljas.
Om du till exempel vill ge åtkomst till GraphQL slutpunkt och beständiga frågeslutpunkter för https://my.domain
du kan använda:
{
"supportscredentials":true,
"supportedmethods":[
"GET",
"HEAD",
"POST"
],
"exposedheaders":[
""
],
"alloworigin":[
"https://my.domain"
],
"maxage:Integer":1800,
"alloworiginregexp":[
""
],
"supportedheaders":[
"Origin",
"Accept",
"X-Requested-With",
"Content-Type",
"Access-Control-Request-Method",
"Access-Control-Request-Headers"
],
"allowedpaths":[
"/content/_cq_graphql/global/endpoint.json",
"/graphql/execute.json/.*"
]
}
Om du har konfigurerat en hjälpsökväg för slutpunkten kan du även använda den i allowedpaths
.
Referensfilter referrer-filter
Förutom CORS-konfigurationen måste ett referensfilter konfigureras så att åtkomst från tredjepartsvärdar tillåts.
Det här filtret görs genom att en lämplig konfigurationsfil för OSGi-referensfiltret läggs till:
- anger ett betrott värdnamn för en webbplats, antingen
allow.hosts
ellerallow.hosts.regexp
, - ger åtkomst till det här värdnamnet.
Om du till exempel vill ge åtkomst för begäranden med referenten my.domain
du kan:
{
"allow.empty":false,
"allow.hosts":[
"my.domain"
],
"allow.hosts.regexp":[
""
],
"filter.methods":[
"POST",
"PUT",
"DELETE",
"COPY",
"MOVE"
],
"exclude.agents.regexp":[
""
]
}
- endast ge åtkomst till betrodda domäner
- se till att ingen känslig information exponeras
- inte använda jokertecken [*] syntax; den här funktionen inaktiverar autentiserad åtkomst till GraphQL-slutpunkten och exponerar den även för hela världen.
Begränsningar limitations
För att skydda dig mot potentiella problem finns det standardbegränsningar för dina frågor:
- Frågan får inte innehålla fler än 1M (1024 * 1024) tecken
- Frågan får inte innehålla fler än 15000 token
- Frågan får inte innehålla fler än 200000 blankstegstoken
Du måste också vara medveten om:
-
Ett fältkonfliktsfel returneras när din GraphQL-fråga innehåller fält med samma namn i två (eller flera) modeller och följande villkor uppfylls:
-
Så här:
- Två (eller flera modeller) används som möjliga referenser, när de definieras som tillåtna Modelltyp i Content Fragment-referensen.
och:
- Dessa två modeller har fält med ett gemensamt namn, vilket betyder att samma namn används i båda modellerna.
och
- Dessa fält har olika datatyper.
-
Till exempel:
-
När två (eller flera) fragment med olika modeller (till exempel
M1
,M2
) används som möjliga referenser (Innehållsreferens eller Fragmentreferens) från ett annat fragment, till exempelFragment1
MultiField/List
-
Och dessa två fragment med olika modeller (
M1
,M2
) har fält med samma namn, men olika typer.
Så här illustrerar du:M1.Title
asText
M2.Title
asText/MultiField
-
Ett fältkonfliktsfel uppstår om GraphQL-frågan innehåller
Title
fält.
-
-
Autentisering authentication
Se Autentisering för fjärrfrågor AEM GraphQL-frågor om innehållsfragment.
Vanliga frågor faqs
Frågor som har uppstått:
-
Q: "Hur skiljer sig GraphQL API för AEM från Query Builder API?"
- A: "AEM GraphQL API ger total kontroll över JSON-utdata och är en branschstandard för att fråga efter innehåll.
I framtiden planerar AEM att investera i AEM GraphQL API."
- A: "AEM GraphQL API ger total kontroll över JSON-utdata och är en branschstandard för att fråga efter innehåll.
Självstudiekurs - Komma igång med AEM Headless och GraphQL tutorial
Söker du en praktisk självstudiekurs? Checka ut Komma igång med AEM Headless och GraphQL en komplett självstudiekurs som visar hur man bygger upp och exponerar innehåll med hjälp av AEM GraphQL API:er och som används av en extern app, i ett headless CMS-scenario.