Antipattern: accedere in modo errato a intestazioni HTTP multivalore in un proxy API

Stai visualizzando la documentazione di Apigee Edge.
Consulta la documentazione di Apigee X.
info

Le intestazioni HTTP sono le coppie nome-valore che consentono alle applicazioni client e ai servizi di backend di trasmettere informazioni aggiuntive rispettivamente su richieste e risposte. Ecco alcuni esempi semplici:

  • L'intestazione della richiesta di autorizzazione trasmette le credenziali utente al server:
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • L'intestazione Content-Type indica il tipo di contenuto della richiesta/risposta inviato:
    Content-Type: application/json

Le intestazioni HTTP possono avere uno o più valori a seconda delle definizioni dei campi di intestazione. Un'intestazione multivalore avrà valori separati da virgole. Ecco alcuni esempi di intestazioni che contengono più valori:

  • Cache-Control: no-cache, no-store, must-revalidate
  • Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • X-Forwarded-For: 10.125.5.30, 10.125.9.125

Apigee Edge consente agli sviluppatori di accedere facilmente alle intestazioni utilizzando variabili di flusso in uno qualsiasi dei criteri Edge o dei flussi condizionali. Di seguito è riportato l'elenco delle variabili che possono essere utilizzate per accedere a un'intestazione di richiesta o a un'intestazione della risposta specifica in Edge:

Variabili di flusso:

  • message.header.header-name
  • request.header.header-name
  • response.header.header-name
  • message.header.header-name.N
  • request.header.header-name.N
  • response.header.header-name.N

Oggetti JavaScript:

  • context.proxyRequest.headers.header-name
  • context.targetRequest.headers.header-name
  • context.proxyResponse.headers.header-name
  • context.targetResponse.headers.header-name

Di seguito è riportato un esempio di criterio AssignMessage che mostra come leggere il valore di un'intestazione della richiesta e memorizzarlo in una variabile:

<AssignMessage continueOnError="false" enabled="true" name="assign-message-default">
  <AssignVariable>
    <Name>reqUserAgent</Name>
    <Ref>request.header.User-Agent</Ref>
  </AssignVariable>
</AssignMessage>

Antipattern

L'accesso ai valori delle intestazioni HTTP nei criteri Edge in modo da restituire solo il primo valore non è corretto e può causare problemi se le intestazioni HTTP specifiche hanno più di un valore.

Le sezioni seguenti contengono esempi di accesso alle intestazioni.

Esempio 1: leggere un'intestazione Accept multivalore utilizzando il codice JavaScript

Supponiamo che l'intestazione Accept abbia più valori, come mostrato di seguito:

Accept: text/html, application/xhtml+xml, application/xml

Ecco il codice JavaScript che legge il valore dall'intestazione Accept:

// Read the values from Accept header
var acceptHeaderValues = context.getVariable("request.header.Accept");

Il codice JavaScript riportato sopra restituisce solo il primo valore dall'intestazione Accept, ad esempio text/html.

Esempio 2: leggere un'intestazione Access-Control-Allow-Headers multivalore nel criterio AssignMessage o RaiseFault

Supponiamo che l'intestazione Access-Control-Allow-Headers abbia più valori, come mostrato di seguito:

Access-Control-Allow-Headers: content-type, authorization

Ecco la parte di codice del criterio AssignMessage o RaiseFault che imposta l'intestazione Access-Control-Allow-Headers:

<Set>
  <Headers>
    <Header name="Access-Control-Allow-Headers">{request.header.Access-Control-Request-Headers}</Header>
  </Headers>
</Set>

Il codice riportato sopra imposta l'intestazione Access-Control-Allow-Headers con solo il primo valore dell' intestazione della richiesta Access-Control-Allow-Headers, in questo esempio content-type.

Impatto

  1. In entrambi gli esempi riportati sopra, tieni presente che vengono restituiti solo il primo valore delle intestazioni multivalore. Se questi valori vengono utilizzati successivamente da un altro criterio nel flusso del proxy API o dal servizio di backend per eseguire una funzione o una logica, potrebbero portare a un risultato imprevisto.
  2. Quando si accede ai valori delle intestazioni delle richieste e li si passa al server di destinazione, le richieste API potrebbero essere elaborate in modo errato dal backend e quindi potrebbero fornire risultati errati.
  3. Se l'applicazione client dipende da valori di intestazione specifici della risposta Edge, allora potrebbe anche essere elaborata in modo errato e fornire risultati errati.

Best practice

  1. Utilizza le variabili di flusso integrate appropriate: request.header.header_name.values.count, request.header.header_name.N, response.header.header_name.values.count, response.header.header_name.N.

    Poi esegui l'iterazione per recuperare tutti i valori da un'intestazione specifica nei criteri di callout JavaScript o Java.

    Esempio: codice JavaScript di esempio per leggere un'intestazione multivalore

    for (var i = 1; i <=context.getVariable('request.header.Accept.values.count'); i++)
    {
      print(context.getVariable('request.header.Accept.' + i));
    }

    Ad esempio, application/xml;q=0.9, */*;q=0.8 verrà visualizzato come un unico valore con il codice riportato sopra.

    Se i valori delle intestazioni devono essere suddivisi utilizzando il punto e virgola come delimitatore, utilizza string.split(";") per separarli in valori.

  2. Utilizza la funzione substring() sulla variabile di flusso request.header.header_name.values nel criterio RaiseFault o AssignMessage per leggere tutti i valori di un'intestazione specifica.

    Esempio: criterio RaiseFault o AssignMessage di esempio per leggere un'intestazione multivalore

    <Set>
      <Headers>
       <Header name="Access-Control-Allow-Headers">{substring(request.header.Access-Control-Request-Headers.values,1,-1)}</Header>
      </Headers>
    </Set>

Per approfondire