Custom request and response headers let you specify additional headers that the load balancer can add to HTTP(S) requests and responses. Depending on the information detected by the load balancer, these headers can include the following information:
- Latency to the client
- Geographic location of the client's IP address
- Parameters of the TLS connection
Custom request headers are supported for backend services, while custom response headers are supported for backend services and backend buckets.
HTTP(S) Load Balancing adds certain headers by default to all HTTP(S) requests and responses that it proxies between backends and clients. For more information, see Target proxies.
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 global external HTTP(S) load balancer makes a request to the backend, the load balancer adds request headers.
The global external HTTP(S) load balancer sets response headers before returning the responses to the client.
To enable custom headers, you specify a list of headers in a property of the backend service or backend bucket.
You specify each header as a header-name:header-value
string. The header must
contain a colon separating the header name and header value. Header names have
the following properties:
- The header name must be a valid HTTP header-field name definition (per RFC 7230).
- The header name must not be
X-User-IP
orCDN-Loop
. - The header name must not begin with
X-Google
,X-Goog-
,X-GFE
orX-Amz-
- The header name must not be
Host
orauthority
. BothHost
andauthority
are special keywords reserved by Google Cloud. You can't modify these headers for Envoy-based load balancers such as the global external HTTP(S) load balancer. 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 added headers.
Header values have the following properties:
- The header value must be a valid HTTP header field definition (per RFC 7230, with obsolete forms disallowed).
- The header value can be blank.
- The header value can include one or more variables, enclosed by curly braces, that expand to values that the load balancer provides. A list of variables allowed in the header value is in the next section.
For example, you might specify a header with two variable names, for the client
region and client city. The gcloud
command-line tool has a flag for
specifying request headers, --custom-request-header
. For example:
--custom-request-header 'X-Client-Geo-Location:{client_region},{client_city}'
For clients located in Mountain View, California, the load balancer adds a header as follows:
X-Client-Geo-Location:US,Mountain View
The general format for the flag is:
--custom-request-header='HEADER_NAME:[HEADER_VALUE]'
Any variable names must be enclosed in curly braces. For example:
--custom-request-header='X-PLACE:{client_city},{client_city_lat_long}'
Use only straight quotation marks ('
) in this command.
Variables that can appear in the header value
The following variables can appear in custom header values.
Variable | Description |
---|---|
cdn_cache_id | Location code and ID of the cache instance used to serve the request.
This is the same value populated in the jsonPayload.cacheId field of
the Cloud CDN request logs in Logging.
|
cdn_cache_status | Current cache status. Values can be hit ,
miss , revalidated , stale ,
uncacheable , or disabled for any object
served by a Cloud CDN-enabled backend.
|
origin_request_header | Reflects the value of the Origin header in the request
for Cross-Origin Resource Sharing (CORS) use cases.
|
client_rtt_msec | Estimated 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, per RFC 2988. Smoothed RTT is an algorithm that deals with variations and anomalies that may occur in RTT measurements. |
client_region | The country (or region) associated with the client's IP address. This
is a Unicode CLDR region code, such as US or
FR . (For most countries, these codes correspond directly
to ISO-3166-2 codes.)
|
client_region_subdivision | Subdivision, e.g. a province or state, of the country associated with
the client's IP address. This is a Unicode CLDR subdivision ID, such as
USCA or CAON . (These Unicode codes are
derived from the subdivisions defined by the ISO-3166-2 standard.)
|
client_city | Name of the city from which the request originated, for example,
Mountain View for Mountain View, California. There is no
canonical list of valid values for this variable. The city names can
contain US-ASCII letters, numbers, spaces, and the following characters:
!#$%&'*+-.^_`|~ .
|
client_city_lat_long | Latitude and Longitude of the city from which the request originated,
for example, 37.386051,-122.083851 for a request from
Mountain View.
|
client_ip_address | The client's IP address. This is the same as the client IP address
that is the next-to-last address in the
X-Forwarded-For
header. |
client_port | The client's source port. |
client_encrypted | Set to true if the connection between the client and the
load balancer is encrypted (using HTTPS, HTTP/2 or HTTP/3), set to
false otherwise.
|
client_protocol | The HTTP protocol used for communication between the client and the
load balancer. One of HTTP/1.0 , HTTP/1.1 ,
HTTP/2 , or HTTP/3 .
|
server_ip_address | The 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 the
X-Forwarded-For
header.
|
server_port | The destination port number that the client connects to. |
tls_sni_hostname | Server name indication (as defined in RFC 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_version | TLS version negotiated between client and load balancer during the
SSL handshake. Possible values include: TLSv1 ,
TLSv1.1 , TLSv1.2 , and TLSv1.3 . If
the client connects using QUIC instead of TLS, the value is
QUIC .
|
tls_cipher_suite | Cipher suite negotiated during the TLS handshake. The value is four
hex digits defined by the
IANA
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_fingerprint | JA3 TLS/SSL fingerprint if the client connects using HTTPS, HTTP/2 or HTTP/3. |
The load balancer expands variables to empty strings when it cannot determine their values. For example:
- Geographic location variables when the IP address's location is unknown
- TLS parameters when TLS is not in use
- The
{origin_request_header}
when the request does not include anOrigin
header - The
{cdn_cache_status}
header when included in a request header
Geographic values (regions, subdivisions, and cities) are estimates based on the client's IP address. From time to time, Google updates the data that provides these values in order to improve accuracy and to reflect geographic and political changes.
Headers added by the load balancer overwrite any existing headers that have the same name. Header names are case insensitive. When header names are passed to an HTTP/2 backend, the HTTP/2 protocol encodes header names as lower case.
In header values, leading whitespace and trailing whitespace are insignificant,
and are not passed to the backend. To allow for curly braces in header values,
the load balancer interprets two opening curly braces ({{
) as
a single opening brace ({
), and two closing curly braces (}}
) as a single
closing brace (}
).
Working with custom request headers
Console
To add custom request headers to an existing backend service:
- Go to the load balancing summary page.
Go to the Load balancing page - Click Backends.
- Click the name of a backend service.
- Click Edit .
- Click Advanced configurations (Session affinity, connection draining timeout, security policies).
- Under Custom request headers, click Add header.
- Enter the Header name and Header value for the custom request header.
- Enter any additional custom request headers.
- Click Save.
To remove a custom request header from a backend service:
- Go to the load balancing summary page.
Go to the Load balancing page - Click Backends.
- Click the name of a backend service.
- Click Edit .
- Click Advanced configurations (Session affinity, connection draining timeout, security policies).
- Click the X next to the name of the custom request header you want to remove.
- Click Save.
gcloud
To specify custom request headers, use the gcloud compute backend-services
create
or
gcloud compute backend-services
update
command
with the --custom-request-header
flag.
To create a backend service with custom request headers:
gcloud compute backend-services create BACKEND_SERVICE_NAME \ --global-health-checks \ --global \ --protocol HTTPS \ --health-checks https-basic-check \ --custom-request-header='HEADER_NAME:[HEADER_VALUE]'
To add more request headers, specify a unique header name and value by
repeating the --custom-request-header
flag.
To add custom headers to an existing backend service:
gcloud compute backend-services update BACKEND_SERVICE_NAME \ --global \ --custom-request-header='HEADER_1_NAME:[HEADER_1_VALUE]' \ --custom-request-header='HEADER_2_NAME:[HEADER_2_VALUE]'
The previous step replaces any headers already in the backend service with the request headers that you specify in the command.
To remove all headers from a backend service:
gcloud compute backend-services update BACKEND_SERVICE_NAME \ --global \ --no-custom-request-headers
API
Make a PATCH
request to the
backendServices.patch
method:
PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME "customRequestHeaders": [ "client_city:Mountain View" ]
Working with custom response headers
Console
To add custom response headers to an existing backend service:
- Go to the load balancing summary page.
Go to the Load balancing page - Click Backends.
- Click the name of a backend service.
- Click Edit .
- Click Advanced configurations (Session affinity, connection draining timeout, security policies).
- Under Custom response headers, click Add header.
- Enter the Header name and Header value for the custom response header.
- Enter any additional custom response headers.
- Click Save.
To remove a custom response header from a backend service:
- Go to the load balancing summary page.
Go to the Load balancing page - Click Backends.
- Click the name of a backend service.
- Click Edit .
- Click Advanced configurations (Session affinity, connection draining timeout, security policies).
- Click the X next to the name of the custom response header you want to remove.
- Click Save.
gcloud
For backend services, use the gcloud compute backend-services
create
or
gcloud compute backend-services
update
command
with the --custom-response-header
flag.
For backend buckets, use the gcloud compute backend-buckets
create
or
gcloud compute backend-buckets
update
command
with the --custom-response-header
flag.
gcloud compute backend-services (create | update) BACKEND_SERVICE_NAME --custom-response-header='HEADER_NAME:[HEADER_VALUE]'
gcloud compute backend-buckets (create | update) BACKEND_BUCKET_NAME --custom-response-header='HEADER_NAME:[HEADER_VALUE]'
Example:
gcloud compute backend-buckets update gaming-lab \ --custom-response-header='X-Frame-Options: DENY'
Example:
The following example shows you how to add a custom response header to support HTTP Strict Transport Security (HSTS):
gcloud compute backend-services update customer-bs-name \ --global \ --custom-response-header='Strict-Transport-Security: max-age=63072000'
API
For backend buckets, use the
Method: backendBuckets.insert
or
Method: backendBuckets.update
API call.
For backend services, use the
Method: backendServices.insert
or
Method: backendServices.update
API call.
Use one of the following API calls:
POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendBuckets/BACKEND_BUCKET_NAME POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices PUT https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/BACKEND_SERVICE_NAME
Add the following snippet to the JSON request body:
"customResponseHeaders":HEADER_NAME:[HEADER_VALUE]
Setting response headers for Cloud Storage
If you need to set HTTP headers on responses from
Cloud Storage—such as Cross-Origin Resource Policy,
X-Frame-Options
, or X-XSS-Protection
headers—Google Cloud offers
the option to use custom headers for Cloud CDN with
Cloud Storage. You can do this by configuring custom headers at the
load balancer backend bucket level, as described on this page.
Custom response headers configured at the backend bucket level are only added to responses if the client request is sent to the load balancer IP address. Custom headers are not added to responses if the client's request was made directly to the Cloud Storage API.
Working with Google Cloud Armor
When you configure a Google Cloud Armor security policy, you can configure Google Cloud Armor to insert a custom header and value. If your Google Cloud Armor security policy is configured to insert the same custom header name as your global external HTTP(S) load balancer or global external HTTP(S) load balancer (classic)'s custom headers, then the header value populated by the load balancer is overwritten by the value specified in your Google Cloud Armor security policy. If you do not want Google Cloud Armor to overwrite the header value, ensure that you do not use the same name.
Limitations
The following limitations apply to custom headers:
- Custom headers are not supported for regional external HTTP(S) load balancers.
- You can specify a maximum of 16 custom request headers for each backend service.
- You can specify a maximum of 16 custom response headers for each backend service.
- The total size of all custom request headers per backend service (name and value combined, before variable expansion) cannot exceed 8 KB.
- The total size of all custom response headers per backend service (name and value combined, before variable expansion) cannot exceed 8 KB.