400 Bad Request - DuplicateHeader

You're viewing Apigee Edge documentation.
Go to the Apigee X documentation.
info

Symptom

The client application gets an HTTP status code of 400 Bad Request with error code protocol.http.DuplicateHeader as a response for API calls.

Error message

Client application gets the following response code:

HTTP/1.1 400 Bad Request

In addition, you may observe an error message similar to the one shown below:

{
   "fault":{
      "faultstring":"Duplicate Header \"Expires\"",
      "detail":{
         "errorcode":"protocol.http.DuplicateHeader"
      }
   }
}

Possible causes

This error occurs if a specific HTTP header that is not allowed to have duplicates in Apigee Edge, appears more than once with same or different values as part of the HTTP request sent by the client to Apigee Edge.

As per RFC 7230, section 3.2.2: Field Order, a sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list, [i.e., #(values)] or the header field is a well-known exception. If Apigee Edge finds a specific header, that is not allowed to have duplicates, more than once in the HTTP request sent by the client, then it responds with 400 Bad Request and error code protocol.http.DuplicateHeader.

Here are the possible causes for this error:

Cause Description Troubleshooting instructions applicable for
Duplicate header in request The HTTP request from client application to Apigee contains duplicate headers. Edge Public and Private Cloud users

Common diagnosis steps

Use one of the following tools/techniques to diagnose this error:

API Monitoring

To diagnose the error using API Monitoring:

  1. Sign in to Apigee Edge UI as a user with an appropriate role.
  2. Switch to the organization in which you want to investigate the issue.

  3. Navigate to the Analyze > API Monitoring > Investigate page.
  4. Select the specific timeframe in which you observed the errors.
  5. Ensure that the Proxy filter is set to All.
  6. Plot Fault Code against Time.
  7. Select a cell which has the fault code protocol.http.DuplicateHeader as shown below:

  8. Information about the fault code protocol.http.DuplicateHeader is displayed as shown below:

  9. Click View logs and expand the row for the failed request.
  10. From the Logs window, note the following details:
    1. Status Code: 400
    2. Fault Source: apigee
    3. Fault Code: protocol.http.DuplicateHeader.
  11. If the Fault Source has the value apigee or MP and the Fault Code has the value protocol.http.DuplicateHeader, then that indicates that the HTTP request from the client contained duplicate headers.

Trace tool

NGINX

To diagnose the error using NGINX access logs:

  1. If you are a Private Cloud user, then you can use NGINX access logs to determine the key information about HTTP 400 errors.
  2. Check the NGINX access logs:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    Where: ORG, ENV and, PORT# are replaced with actual values.

  3. Search to see if there are any 400 errors during a specific duration (if the problem happened in the past) or if there are any requests still failing with 400.
  4. If you do find any 400 errors with the X-Apigee-fault-code matching the value of protocol.http.DuplicateHeader, then determine the value of the X-Apigee-fault-source.

    Sample 400 error from NGINX access log:

    The above sample entry from NGINX Access log has the following values for X-Apigee- fault-code and X-Apigee-fault-source:

    Response Headers Value
    X-Apigee-fault-code protocol.http.DuplicateHeader
    X-Apigee-fault-source MP

Cause: Duplicate Header in request

Diagnosis

  1. Determine the Fault Code and Fault Source for the error observed using API Monitoring or NGINX access logs as explained in Common diagnosis steps.
  2. If the Fault Source has the value apigee or MP, then this indicates that the request sent by the client application to Apigee contains duplicate headers.
  3. You can determine the actual header that is sent more than once as part of the request using one of the following methods:

    Error message

    Using the error message

    1. If you have access to the complete error message received from Apigee Edge, then refer to the faultstring. The faultstring contains the header name that has been sent more than once.

      Sample error message:

      "faultstring":"Duplicate Header \"Expires\""
      
    2. In the above error message, you can see that the header Expires is sent more than once as seen in the faultstring.

    Actual request

    Using the actual request

    1. If you have access to the actual request made by the client application, then perform the following steps:

      1. Verify the list of headers passed in the request.
      2. If you find that a particular header appears more than once in the request with the same value or different values , then that’s the cause for this error.

      Sample Request:

      curl https://HOST_ALIAS/duplicateheadertest -v -H "Expires: Mon, 21 June 2021 07:28:00 GMT" -H "Expires: Mon, 21 June 2021 07:28:00 GMT"
      

      In the above example request, the header Expires is sent more than once. Therefore, this request fails with the 400 Bad Request error and the error code: protocol.http.DuplicateHeader.

    2. Alternatively, if you have access to the client logs, you can see if you have information about the actual request made to Apigee Edge and determine the header that is sent more than once.

Resolution

Fix duplication

Option #1 [Recommended Option] Fix the client application to not include duplicate headers

  1. Analyze the reason for the specific client to send a duplicate header. For example, Expires in the above case. Verify that it is okay for the API proxies to accept the duplicate header. Typically, it is not desirable as per HTTP specification RFC7230.
  2. If it is not desirable, modify your client application to not send duplicate headers.

    In the example discussed above, it is noticed that header Expires is sent twice with the same value, which is not desirable. You can fix the issue by passing the Expires header only once as shown below:

    curl https://HOST_ALIAS/duplicateheadertest -v -H "Expires: Mon, 21 June 2021 07:28:00 GMT"
    
  3. If it is desirable and you want to allow the duplicate headers, go to Option #2 Using CwC property.

CwC

Option #2 Using CwC property

Apigee provides a CwC property HTTPHeader.<HeaderName> ,which allows client applications and target servers to send duplicate headers to API proxies in Apigee Edge.

CwC property Values
HTTPHeader.<HeaderName> allowDuplicates,multivalued

For example, the following property can be set on the Message Processors to allow duplicates and multiple values for the header Expires.

HTTPHeader.Expires=allowDuplicates, multiValued
  1. If you are a Private Cloud user, you can configure the property to prevent Apigee Edge from raising a 400 Bad Request error, even if the request contains duplicate headers using the Configuring Message Processors to use duplicate headers how-to guide.
  2. If you are a Public Cloud user, contact Apigee Edge Support to configure this property for your organization.

Specification

Apigee expects the client application to not send duplicate headers as part of the request according to the following RFC specifications:

Specification
RFC 7230, section 3.2.2: Field Order
RFC 7230, section 3.2 Header Fields

If you still need any assistance from Apigee Support, go to Must gather diagnostic information.

Must gather diagnostic information

Gather the following diagnostic information, and then contact Apigee Edge Support.

If you are a Public Cloud user, provide the following information:

  • Organization name
  • Environment name
  • API Proxy name
  • Complete curl command used to reproduce the 400 error
  • Trace file for the API requests

If you are a Private Cloud user, provide the following information:

  • Complete error message observed for the failing requests
  • Environment name
  • API proxy bundle
  • Complete curl command you used to reproduce the 400 error
  • Trace file for the API requests
  • NGINX access logs:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    Where: ORG, ENV and PORT# are replaced with actual values.

  • Message Processor system logs /opt/apigee/var/log/edge-message-processor/logs/system.log