Anti-pattern: accedere in modo errato alle intestazioni HTTP a più valori in un proxy API

Stai visualizzando la documentazione relativa a Apigee e Apigee ibrido.
Visualizza la documentazione di Apigee Edge.

Le intestazioni HTTP sono le coppie nome-valore che consentono le applicazioni client e i servizi di backend per trasmettere ulteriori informazioni rispettivamente sulle richieste e sulle risposte. Ecco alcuni semplici esempi:

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

Le intestazioni HTTP possono avere uno o più valori a seconda del definizioni del campo di intestazione. Un'intestazione con più valori 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 consente agli sviluppatori di accedere facilmente alle intestazioni utilizzando variabili di flusso in uno qualsiasi dei criteri o flussi condizionali. Ecco un elenco di variabili che possono essere utilizzate per accedere a una specifica intestazione di richiesta o risposta in Apigee:

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

Accedere ai valori delle intestazioni HTTP nei criteri Apigee in modo da restituire solo il primo valore non è corretta e può causare problemi se l'intestazione HTTP specifica contiene più di un valore.

Le seguenti sezioni contengono esempi di accesso all'intestazione.

Esempio 1: leggere un'intestazione Accept a più valori utilizzando il codice JavaScript

Tieni presente che l'intestazione Accept ha 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: leggi un'intestazione Access-Control-Allow-Headers con più valori nel criterio AssignMessage o RaiseFault

Tieni presente che l'intestazione Access-Control-Allow-Headers ha più valori, come mostrato di seguito:

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

Ecco la parte di codice dell'impostazione del criterioAssignMessage o RaiseFault per 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 precedenti, nota che viene restituito solo il primo valore delle intestazioni a più valori. Se questi valori vengono successivamente utilizzati da un altro criterio nel flusso del proxy API o dal servizio di backend eseguire alcune funzioni o logiche, ciò potrebbe portare a un risultato o risultato inaspettato.
  2. Quando i valori dell'intestazione della richiesta vengono acceduti e trasmessi al server di destinazione, le richieste API potrebbero essere elaborate in modo errato dal backend e quindi fornire risultati errati.
  3. Se l'applicazione client dipende da valori di intestazione specifici della risposta di Apigee, potrebbe anche essere elaborata in modo errato e fornire risultati errati.

Best practice

  1. Fai riferimento alla forma request.header.header_name.values.string della variabile di flusso per leggere tutti i valori di un'intestazione specifica.

    Esempio: frammento di esempio che potrebbe essere utilizzato in RaiseFault oAssignMessage per leggere un'intestazione con più valori

    <Set>
      <Headers>
        <Header name="Inbound-Headers">{request.header.Accept.values.string}</Header>
      </Headers>
    </Set>
  2. Se vuoi accedere singolarmente a ciascuno dei valori distinti, puoi utilizzare le variabili di flusso predefinite 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 con più valori

    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 due valori con il codice riportato sopra. Il primo valore è application/xml;q=0.9 e il secondo sarà */*;q=0.8.

    Se i valori dell'intestazione devono essere suddivisi utilizzando il punto e virgola come delimitatore, puoi utilizzare string.split(";") all'interno del callout JavaScript per separare i valori distinti.

  3. In alternativa, puoi utilizzare la funzione substring() disponibile all'interno di un modello di messaggio sulla variabile di flusso request.header.header_name.values per leggere tutti i valori di un'intestazione specifica.

    Esempio: utilizza substring() all'interno di un modello di messaggio per leggere un'intestazione completa con più valori

    <Set>
      <Headers>
       <Header name="Inbound-Headers">{substring(request.header.Accept.values,1,-1)}</Header>
      </Headers>
    </Set>

Per approfondire