Create custom headers in URL maps

This page describes how custom headers work in URL maps used byregional external Application Load Balancers.

Custom request and response headers let you specify additional headers thatthe load balancer can add to HTTP(S) requests and responses. Depending on theinformation that the load balancer detects, these headers can include thefollowing information:

  • Latency to the client
  • Parameters of the TLS connection

  • Geographic location of the client's IP address

Important: Global external Application Load Balancers support header transformations in theURLmapas well as in thebackendservice. However, theregional external Application Load Balancers only support header transformations in URL maps.

Before you begin

If necessary, update to the latest version of the Google Cloud CLI:

gcloud components update

How custom headers work

Custom headers work as follows:

  • When the load balancer makes a request to the backend, the loadbalancer adds request headers.

    The load balancer adds custom request headers only to the client requests, notto the health check probes. If your backend requires a specific header forauthorization that is missing from the health check packet, the health checkmight fail.

  • The load balancer sets response headers before returning aresponse to the client.

To enable custom headers for regional external Application Load Balancers,you specify a list of header names and header values in the URL mapconfiguration file.

Header names must have the following properties:

  • The header name must be a valid HTTP header-field name definitionperRFC 7230.
  • The header name must not beX-User-IP.
  • The header name must not begin withX-Google,X-Goog-,X-GFE,orX-Amz-.
  • The following hop-by-hop headers must not be used:Keep-Alive,Transfer-Encoding,TE,Connection,Trailer, andUpgrade. In accordance withRFC 2616,these headers are not stored by caches or propagated by the target proxies.
  • The header name must not beHost orauthority. BothHost andauthorityare special keywords reserved by Google Cloud. You can't modify theseheaders for Envoy-based load balancers.Instead, we recommend that you create other custom headers (for example,MyHost) so that you don't interfere with the reserved header names.
  • A header name must not appear more than once in the list of headers.

Header names are case-insensitive. When header names are passed to an HTTP/2backend, the HTTP/2 protocol encodes header names as lowercase.

Header values must have the following properties:

  • The header value must be a valid HTTP header field definitionperRFC 7230,with obsolete forms disallowed.
  • The header value can't be blank. Blank headers are rejected.
  • The header value can include one or more variables, enclosed by curly braces,that expand to values that the load balancer provides. For a complete list ofvariables allowed in the header value, seeVariables thatcan appear in the header value.

In header values, leading whitespace and trailing whitespace are insignificantand are not passed to the backend. To allow for curly braces in header values,the load balancer interprets two opening curly braces ({{) asa single opening brace ({), and two closing curly braces (}}) as a singleclosing brace (}).

Add request or response headers

To add request or response headers, use the gcloud CLI to editthe URL map as follows:

Note: If you are using the Google Cloud console to add the request and responseheaders in the URL map, you need to enter the host address in theHosts field and the path matcher section of the following YAML inthePath matcher field.

Regional

    gcloud compute url-maps editURL_MAP_NAME \        --region=REGION

Following is a sample YAML file that shows you how to use variables in custom headers:

   defaultService: regions/REGION/backendServices/BACKEND_SERVICE_1   name: regional-lb-map   region: region/REGION   hostRules:   - hosts:     - '*'     pathMatcher: matcher1   pathMatchers:   - defaultService: regions/REGION/backendServices/BACKEND_SERVICE_1     name: matcher1     routeRules:       - matchRules:           - prefixMatch: /PREFIX         priority:PRIORITY # 0 is highest         routeAction:           weightedBackendServices:             - backendService: regions/REGION/backendServices/BACKEND_SERVICE_1               weight: 100               headerAction:                 requestHeadersToAdd:                 - headerName: X-header-1-client-region                   headerValue: "{client_region}"                 - headerName: X-header-2-client-ip-port                   headerValue: "{client_ip_address}, {client_port}"                   replace: True                 requestHeadersToRemove:                 - header-3-name                 responseHeadersToAdd:                 - headerName: X-header-4-server-ip-port                   headerValue: "{server_ip_address}, {server_port}"                   replace: True                 responseHeadersToRemove:                 - header-5-name                 - header-6-name

Note the following behaviors:

  • If a response header with custom variables resolves to an empty string, it isremoved.
  • If a request header with custom variables resolves to an empty string, it isretained with an empty string placeholder.
  • If a custom request header includes a custom variable, and an incoming clientrequest also includes the same header, the client request header value will bereplaced with the new value provided by the load balancer's custom header.

Variables that can appear in the header value

The following variables can appear in custom header values.

VariableDescription
client_regionThe country (or region) associated with the client's IP address. This is a Unicode CLDR region code, such asUS orFR. (For most countries, these codes correspond directly toISO-3166-2 codes.)
client_rtt_msecEstimated round-trip transmission time between the load balancer and the HTTP(S) client, in milliseconds. This is the smoothed round-trip time (SRTT) parameter measured by the load balancer's TCP stack, perRFC 2988. Smoothed RTT is an algorithm that deals with variations and anomalies that may occur in RTT measurements.
client_ip_addressThe client's IP address. This is usually the same as the client IP address that is the next-to-last address in theX-Forwarded-For header, unless the client is using a proxy or theX-Forwarded-For header has been tampered with.
client_portThe client's source port.
client_encryptedtrue if the connection between the client and the load balancer is encrypted (using HTTPS, HTTP/2, or HTTP/3); otherwise,false.
client_protocolThe HTTP protocol used for communication between the client and the load balancer. One ofHTTP/1.0,HTTP/1.1,HTTP/2, orHTTP/3.
origin_request_headerReflects the value of theOrigin header in the request for Cross-Origin Resource Sharing (CORS) use cases.
server_ip_addressThe IP address of the load balancer that the client connects to. This can be useful when multiple load balancers share common backends. This is the same as the last IP address in theX-Forwarded-For header.
server_portThe destination port number that the client connects to.
tls_sni_hostnameServer name indication (as defined inRFC 6066), if provided by the client during the TLS or QUIC handshake. The hostname is converted to lowercase and with any trailing dot removed.
tls_versionTLS version negotiated between client and load balancer during the SSL handshake. Possible values include:TLSv1,TLSv1.1,TLSv1.2, andTLSv1.3. If the client connects using QUIC instead of TLS, the value isQUIC.
tls_cipher_suiteCipher suite negotiated during the TLS handshake. The value is four hex digits defined by theIANA TLS Cipher Suite Registry, for example,009C for TLS_RSA_WITH_AES_128_GCM_SHA256. This value is empty for QUIC and for unencrypted client connections.
tls_ja3_fingerprintJA3 TLS/SSL fingerprint if the client connects using HTTPS, HTTP/2 or HTTP/3.
tls_ja4_fingerprintJA4 TLS/SSL fingerprint if the client connects using HTTPS, HTTP/2 or HTTP/3.

The load balancer expands variables to empty strings when it can't determinetheir values. For example:

  • TLS parameters when TLS is not in use
  • The{origin_request_header} when the request does not include anOriginheader

  • Geographic location variables when the IP address's location is unknown

Geographic values are estimates based on the client's IP address. From time totime, Google updates the data that provides these values in order to improveaccuracy and to reflect geographic and political changes. Even if the originalX-Forwarded-For header contains valid location information, Google estimatesclient locations by using the source IP address information contained in packetsreceived by the load balancer.

Mutual TLS custom headers

The following additional header variables are available if mutual TLS (mTLS) isconfigured on the load balancer's TargetHttpsProxy.

VariableDescription
client_cert_presenttrue if the client has provided a certificate during the TLS handshake; otherwise,false.
client_cert_chain_verifiedtrue if the client certificate chain is verified against a configuredTrustStore; otherwise,false.
client_cert_errorPredefined strings representing the error conditions. For more information about the error strings, seemTLS client validation modes.
client_cert_sha256_fingerprintBase64-encoded SHA-256 fingerprint of the client certificate.
client_cert_serial_numberThe serial number of the client certificate. If the serial number is longer than 50 bytes, the stringclient_cert_serial_number_exceeded_size_limit is added toclient_cert_error, and the serial number is set to an empty string.
client_cert_spiffe_id

TheSPIFFE ID from the subject alternative name (SAN) field. If the value is not valid or exceeds 2048 bytes, the SPIFFE ID is set to an empty string.

If the SPIFFE ID is longer than 2048 bytes, the stringclient_cert_spiffe_id_exceeded_size_limit is added toclient_cert_error.

client_cert_uri_sans

Comma-separated Base64-encoded list of the SAN extensions of type URI. The SAN extensions are extracted from the client certificate. The SPIFFE ID is not included in theclient_cert_uri_sans field.

If theclient_cert_uri_sans is longer than 512 bytes, the stringclient_cert_uri_sans_exceeded_size_limit is added toclient_cert_error, and the comma-separated list is set to an empty string.

client_cert_dnsname_sans

Comma-separated Base64-encoded list of the SAN extensions of type DNSName. The SAN extensions are extracted from the client certificate.

If theclient_cert_dnsname_sans is longer than 512 bytes, the stringclient_cert_dnsname_sans_exceeded_size_limit is added toclient_cert_error, and the comma-separated list is set to an empty string.

client_cert_valid_not_beforeTimestamp (RFC 3339 date string format) before which the client certificate is not valid. For example,2022-07-01T18:05:09+00:00.
client_cert_valid_not_afterTimestamp (RFC 3339 date string format) after which the client certificate is not valid. For example,2022-07-01T18:05:09+00:00.
client_cert_issuer_dn

Base64-encoded full Issuer field from the certificate.

If theclient_cert_issuer_dn is longer than 512 bytes, the stringclient_cert_issuer_dn_exceeded_size_limit is added toclient_cert_error, andclient_cert_issuer_dn is set to an empty string.

client_cert_subject_dn

Base64-encoded full Subject field from the certificate.

If theclient_cert_subject_dn is longer than 512 bytes, the stringclient_cert_subject_dn_exceeded_size_limit is added toclient_cert_error, andclient_cert_subject_dn is set to an empty string.

client_cert_leaf

The client leaf certificate for an established mTLS connection where the certificate passed validation. Certificate encoding is compliant withRFC 9440: the binary DER certificate is encoded using Base64 (without line breaks, spaces, or other characters outside the Base64 alphabet) and delimited with colons on either side.

Ifclient_cert_leaf exceeds 16 KB unencoded, the stringclient_cert_validated_leaf_exceeded_size_limit is added toclient_cert_error, andclient_cert_leaf is set to an empty string.

client_cert_chain

The comma-delimited list of certificates, in standard TLS order, of the client certificate chain for an established mTLS connection where the client certificate passed validation, not including the leaf certificate. Certificate encoding is compliant withRFC 9440.

If the combined size ofclient_cert_leaf andclient_cert_chain before Base64 encoding exceeds 16 KB, the stringclient_cert_validated_chain_exceeded_size_limit is added toclient_cert_error, andclient_cert_chain is set to an empty string.

Limitations

The following limitations apply:

  • You can't configure custom headers on backend services used byregional external Application Load Balancers.
  • The following custom header variables aren't supported withregional external Application Load Balancers:

    • cdn_cache_id
    • cdn_cache_status
    • client_region_subdivision
    • client_city
    • client_city_lat_long

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.