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 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 su richieste e 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 a 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

Ecco un esempio di criterioAssignMessage che mostra come leggere il valore di un'intestazione della richiesta e archiviare 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

Accesso 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: leggere un'intestazione Access-Control-Allow-Headers a più valori nel criterio AssegnaMessage 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 del 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 si accede ai valori dell'intestazione delle richieste e vengono passati al server di destinazione, le richieste API possono essere elaborati dal backend in modo errato, potrebbero restituire risultati errati.
  3. Se l'applicazione client dipende da valori di intestazione specifici della risposta Apigee, potrebbe anche elaborare in modo errato e restituire risultati errati.

Best practice

  1. Fai riferimento a 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 desideri un accesso individuale a ciascuno dei singoli valori, puoi utilizzare il metodo variabili di flusso integrate: 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 è */*;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: utilizzo di substring() all'interno di un modello di messaggio per leggere un'intestazione multivalore completa

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

Per approfondire