Cross-origin configuration
Background introduction
The link propagation protocol allows the transmission of tracing information in a distributed system, usually by adding special request headers to the HTTP request header to pass tracing information such as traceId and spanId.
Cross-origin resource sharing (CORS)
CORS (Cross-origin resource sharing) is a mechanism that uses additional HTTP headers to tell the browser to allow a web application running in one origin (domain) to be allowed to access resources from another origin. To ensure security, the browser will perform a preflight request for certain cross-origin requests (especially requests with custom headers).
Preflight Request
When using XMLHttpRequest or Fetch API for cross-origin requests, if the request uses one of the following, the browser will first send an OPTIONS request, called a preflight request, to check whether the server allows the actual request:
-
HTTP methods other than GET, POST, or HEAD are used.
-
Custom request headers are used (i.e., not standard headers listed in the CORS specification, such as Content-Type, Accept, Authorization, etc.).
Since OpenTelemetry needs to add custom tracing information (such as traceparent, tracestate) to the request header, this triggers the browser's preflight request.
Example
Suppose we have an TingYun trace header traceparent, which has the following format:
X-Tingyun:c=B|b1t76Pq_FnI;x=4d42de860dc64124;u=base64#c3p3YW5zaGVuZw==
When a browser makes a cross-origin request containing this request header, it first sends a preflight request:
OPTIONS /api/resource HTTP/1.1
Host: api.example.com
Origin: http://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Tingyun
The server needs to respond to allow the request:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: X-Tingyun
If the server allows preflight requests, the browser will send the actual request:
POST /api/resource HTTP/1.1
Host: api.example.com
Origin: http://example.com
X-Tingyun:c=B|b1t76Pq_FnI;x=4d42de860dc64124;u=base64#c3p3YW5zaGVuZw==
Configuration Notes
NGINX Configuration Example
Assuming your backend service is running behind NGINX. We need to configure NGINX to handle preflight requests and allow custom request headers.
server {
listen 80;
server_name api.example.com;
# Define a location block to handle preflight requests
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'X-Tingyun';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
# Handle the actual request
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Expose-Headers' 'X-Tingyun-Data';
proxy_pass http://backend_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Configuration Instructions
- Handle preflight request: In the location /api/ block, we first check if the request method is OPTIONS. If so, CORS-related response headers are added and a 204 status code is returned.
- Add response headers: For all requests (including pre-check requests and actual requests), we add
Access-Control-Allow-Origin
,Access-Control-Allow-Methods
, andAccess-Control-Allow-Headers
headers. These headers allow cross-domain requests and allow custom headers (such as traceparent and tracestate). - Access-Control-Max-Age: Used to configure the cache time of pre-check requests to avoid sending pre-check requests for each request.
- 'Access-Control-Expose-Headers' 'X-Tingyun-Data': This request header is used by the Web SDK to obtain the return performance data. It can be configured in a fixed format.
Apache httpd Configuration Example
check mod_headers、mod_rewrite model
In Apache, the CORS related header Settings need to rely on the mod_headers and mod_rewrite modules. First, you need to make sure that the module is enabled. Locate the following line in the httpd.conf file and make sure it is not commented out.
LoadModule headers_module modules/mod_headers.so
LoadModule rewrite_module modules/mod_rewrite.so
配置跨域设置
<Location /api/>
# preflight
<IfModule mod_headers.c>
SetEnvIf Request_Method OPTIONS preflight
Header add Access-Control-Allow-Methods "GET, POST, OPTIONS" env=preflight
Header add Access-Control-Allow-Headers "X-Tingyun" env=preflight
Header add Access-Control-Max-Age 1728000 env=preflight
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^ - [R=204,L]
</IfModule>
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Expose-Headers "X-Tingyun-Data"
</Location>
Testing and verification
Testing pre-check requests
Use tools (such as curl or Postman) to send an OPTIONS request with a custom header to ensure that the server returns the correct CORS header.
curl -X OPTIONS -H "Origin: http://example.com" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Tingyun" http://api.example.com/api/resource
Actual request
After confirming that the pre-check request passes, send the actual request to verify that all header information is processed correctly.
curl -X POST -H "Origin: http://example.com" -H "c=B|b1t76Pq_FnI;x=4d42de860dc64124;u=base64#c3p3YW5zaGVuZw==" -H "Content-Type: application/json" -d '{"data": "example"}' http://api.example.com/api/resource
With the above configuration, NGINX can correctly handle cross-origin requests containing OpenTelemetry request headers while complying with the CORS specification.
Configuration Guide
Web SDK supports multiple manufacturers and custom link propagation request headers, so it needs to be configured as needed
Get the request headers to be configured
Access the menu Web/Application/Settings/Link Tracking
, find View the request headers to be configured
, click to copy the pop-up request headers for the corresponding cross-domain configuration
nginx example configuration
server {
listen 80;
server_name api.example.com;
# Define a location block to handle pre-check requests
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'X-Tingyun traceparent, tracestate';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
# Process the actual request
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Expose-Headers' 'X-Tingyun-Data';
proxy_pass http://backend_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The above configuration declares the link propagation protocol of two vendors, Tingyun
and w3c
Appendix
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
https://opentelemetry.io/docs/context-propagation/
https://www.w3.org/TR/trace-context/