使用 javascript 获取 Cloudflare 的 HTTP_CF_IPCOUNTRY 标头?

Posted

技术标签:

【中文标题】使用 javascript 获取 Cloudflare 的 HTTP_CF_IPCOUNTRY 标头?【英文标题】:Get Cloudflare's HTTP_CF_IPCOUNTRY header with javascript? 【发布时间】:2015-12-03 23:37:06 【问题描述】:

有很多关于如何使用 javascript 获取 http 标头的问题,但由于某种原因,它们没有显示 HTTP_CF_IPCOUNTRY 标头。

如果我尝试使用 php echo $_SERVER["HTTP_CF_IPCOUNTRY"];,它可以工作,所以 CF 工作正常。

是否可以使用 javascript 获取此标头?

【问题讨论】:

你指的是哪个 javascript - 客户端或服务器端(节点)? 由于我的回答添加了网络工作者标签。希望你不介意:-) 您可以通过以下方式访问:cloudflare-quic.com/b/headers 或 cloudflare.com/cdn-cgi/trace 参考:cloudflare-quic.com/b 和 github.com/fawazahmed0/cloudflare-trace-api 【参考方案1】:

@Quentin 的回答是正确的,适用于任何试图访问服务器标头的 javascript 客户端。

但是,由于此问题特定于 Cloudlfare,并且特定于通常在 HTTP_CF_IPCOUNTRY 标头中获取 2 个字母的国家/地区 ISO,因此我相信我有一个最适合所问问题的解决方法。

下面是我在前端 Ember App 上使用的代码摘录,位于 Cloudflare...和 ​​varnish... 和 fastboot... 后面。

function parseTrace(url)
    let trace = [];
    $.ajax(url,
        
            success: function(response)
                let lines = response.split('\n');
                let keyValue;

                lines.forEach(function(line)
                    keyValue = line.split('=');
                    trace[keyValue[0]] = decodeURIComponent(keyValue[1] || '');

                    if(keyValue[0] === 'loc' && trace['loc'] !== 'XX')
                        alert(trace['loc']);
                    

                    if(keyValue[0] === 'ip')
                        alert(trace['ip']);
                    

                );

                return trace;
            ,
            error: function()
                return trace;
            
        
    );
;

let cfTrace = parseTrace('/cdn-cgi/trace');

性能真的很棒,在调用其他API或函数之前不要害怕调用这个函数。我发现它与从 Cloudflare 的缓存中检索静态资源一样快,有时甚至更快。您可以在 Pingdom 上运行配置文件来确认这一点。

【讨论】:

你能解释一下如何使用它吗?我应该在哪里说明我要定位的国家/地区代码?【参考方案2】:

假设您在谈论客户端 JavaScript:不,这是不可能的。

    浏览器向服务器发出 HTTP 请求。 服务器会注意到请求来自哪个 IP 地址 服务器在数据库中查找该 IP 地址并找到匹配的国家/地区 服务器将该国家/地区传递给 PHP

数据甚至从不靠近浏览器。

要让 JavaScript 访问它,您需要使用服务器端代码读取它,然后将其放入响应中返回给浏览器。

【讨论】:

很抱歉,但在问题的上下文中,这具有误导性。 Cloudflare 网络已经为您完成了这项工作(它知道人们在哪个国家/地区)并将其传递到 CF_IPCOUNTRY 标头中。因此,虽然您的方法是正确的,但第 2 步和第 3 步应该只是说Read the HTTP_CF_IPCOUNTRY header。如果您尝试仅从 IP 查找国家/地区,那将是一个很大的 PITA,并且随时都会发生变化。 Cloudflare 的标头应该更准确。 @Simon_Weaver — 在这种情况下,“服务器”是“Cloudflare 服务器”(因为这是浏览器正在与之通信的服务器)。事实上第 4 步涉及从 cloudflare 服务器到运行 PHP 的服务器的额外 HTTP 请求与问题无关(这是关于获取客户端信息)。【参考方案3】:

fetch('https://cloudflare-quic.com/b/headers').then(res=>res.json()).then(data=>console.log(data.headers['Cf-Ipcountry']))

参考:

https://cloudflare-quic.com/b

https://cloudflare-quic.com/b/headers

有用的链接:

https://www.cloudflare.com/cdn-cgi/trace

https://github.com/fawazahmed0/cloudflare-trace-api

【讨论】:

【参考方案4】:

是的,您必须访问服务器 - 但它不一定是您的服务器。

我有一个购物车,其中几乎所有内容都由 Cloudflare 缓存 - 所以我觉得去我的服务器只获取国家代码是愚蠢的。

相反,我在 Cloudflare 上使用网络工作者(额外收费):

addEventListener('fetch', event => 
  event.respondWith(handleRequest(event.request))
)

async function handleRequest(request) 
  
  var countryCode = request.headers.get('CF-IPCountry');
  
  return new Response(
    
    JSON.stringify( countryCode ),

     headers: 
      "Content-Type": "application/json"
    );

您可以将此脚本映射到诸如/api/countrycode 之类的路由,然后当您的客户端发出 HTTP 请求时,它基本上会立即返回(对我来说大约是 10 毫秒)。

 /api/countrycode
 
    "countryCode": "US"
 

加上一些额外的东西:

您不能在所有服务级别上都使用网络工作者 最好在与备份相同的 URL 上部署实际的 Web 服务(如果 Web 工作者未启用或支持或在开发期间) 有费用,但应该可以忽略不计 似乎有一个新功能可以将单个路径映射到单个脚本。这就是我在这里所做的。我认为这曾经是企业独有的功能,但现在我可以使用它,这很棒。 别忘了它可能是 TOR 网络的 T1

自从我写这篇文章以来,他们已经在Request.cf 上公开了更多的属性——即使是价格较低的计划:

https://developers.cloudflare.com/workers/runtime-apis/request#incomingrequestcfproperties

您现在可以获取cityregion 甚至longitudelatitude,而无需使用地理查找数据库。

【讨论】:

重要提示:看起来当您有多个网络工作者时,它们不会以任何优先顺序运行。因此,如果您已经在使用此功能,您可能需要将此逻辑组合到您的主 webworker 脚本中。此外,如果您还没有使用网络工作者,您可能不想为此每月支付 5 美元! 感谢您,帮助我们在wiki.polkadot.network 进行重定向? 编辑队列已满,所以我将在此处发布我的 cmets。 Cloudflare 每天为您提供 100,000 个免费的 Web Worker 请求,您可以将其配置为在超过 100,000 个时通过将请求传递到您的服务器来优雅地失败。因此,如果您的网站很少超过这个数字,那么这是一个很好的免费选择。 @Simon_Weaver 也没有提到使用 XMLHttpRequest 对象,您可以使用浏览器 javascript 通过查询 /api/countrycode 或您设置的任何路线来查询国家/地区。【参考方案5】:

我已经采纳了 Don Omondi 的答案,并将其转换为 Promise 函数以方便使用。

function get_country_code() 
    return new Promise((resolve, reject) => 
        var trace = []; 
        jQuery.ajax('/cdn-cgi/trace', 
            success: function(response) 
                var lines = response.split('\n');
                var keyValue;
                for (var index = 0; index < lines.length; index++) 
                    const line = lines[index];
                    keyValue = line.split('=');
                    trace[keyValue[0]] = decodeURIComponent(keyValue[1] || '');
                    if (keyValue[0] === 'loc' && trace['loc'] !== 'XX') 
                        return resolve(trace['loc']);
                    
                
            ,
            error: function() 
                return reject(trace);
            
        );

    );

使用示例

get_country_code().then((country_code) => 
    // do something with the variable country_code
).catch((err) => 
    // caught the error, now do something with it
);

【讨论】:

你能解释一下如何使用它吗?我应该在哪里说明我要定位的国家代码?我试过 document.write(country_code);什么都没有发生。

以上是关于使用 javascript 获取 Cloudflare 的 HTTP_CF_IPCOUNTRY 标头?的主要内容,如果未能解决你的问题,请参考以下文章

javascript 只使用Javascript获取Gravatar

javascript 使用formData进行JavaScript获取

JavaScript 使用JavaScript获取URL参数

JavaScript 使用JavaScript获取URL参数

javascript 使用JavaScript获取查询字符串参数

JavaScript 使用Javascript设置,获取和删除cookie