Anti-pattern: accesso errato alle intestazioni HTTP multivalore in un proxy API

Stai visualizzando la documentazione di Apigee Edge.
Vai alla documentazione di Apigee X.
informazioni

Le intestazioni HTTP sono coppie di valori nome che consentono alle applicazioni client e ai servizi di backend di passare informazioni aggiuntive 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 delle definizioni dei campi 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 Edge consente agli sviluppatori di accedere facilmente alle intestazioni utilizzando le variabili di flusso in qualsiasi criterio Edge o flusso condizionale. Di seguito è riportato l'elenco di variabili che possono essere utilizzate per accedere a un'intestazione di richiesta o 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 criterio di AssegnaMessage di esempio che mostra come leggere il valore di un'intestazione di richiesta e archiviarlo 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 perimetrali in un modo che restituisca solo il primo valore non è corretto e può causare problemi se le intestazioni HTTP specifiche hanno più di un valore.

Le seguenti sezioni contengono esempi di accesso alle intestazioni.

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

Considera 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 dell'intestazione Accept, come text/html.

Esempio 2: leggi un'intestazione Access-Control-Allow-Headers a più valori nel criterioAssignMessage o RaiseFault

Considera 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 criterio AssegnaMessage o AlzaFault 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 solo con 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 proxy API o dal servizio di backend per eseguire una funzione o logica, potrebbe portare a un risultato o un risultato imprevisto.
  2. Quando l'accesso ai valori dell'intestazione della richiesta e il trasferimento al server di destinazione, le richieste API potrebbero essere elaborate in modo errato dal backend e, di conseguenza, potrebbero restituire risultati errati.
  3. Se l'applicazione client dipende da valori di intestazione specifici della risposta Edge, potrebbe anche essere elaborata in modo errato e restituire 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.

    Ripeti l'operazione per recuperare tutti i valori da un'intestazione specifica nei criteri relativi ai callout JavaScript o Java.

    Esempio: codice JavaScript di esempio per leggere un'intestazione di 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 apparirà come valore unico con il codice riportato sopra.

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

  2. Usa la funzione substring() nella variabile di flusso request.header.header_name.values nel criterio AlzaFault oAssignMessage per leggere tutti i valori di un'intestazione specifica.

    Esempio: criterio RaiseFault oAssignMessage di esempio per leggere un'intestazione di più valori

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

Per approfondire