我所有的浏览器都没有发送原始标头

Posted

技术标签:

【中文标题】我所有的浏览器都没有发送原始标头【英文标题】:all of my browsers are not sending the origin header 【发布时间】:2012-12-23 02:58:07 【问题描述】:

我正在尝试将图像加载到画布元素中,然后在 toDataURL() 中提取数据。

我的网站使用 Ruby on Rails 2.3 运行

我从 aws s3 提供图像。我已经设置了 cors:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

我有一个画布元素:

<canvas id="explain_canvas"></canvas>

好的,这里有一些背景知识。我最初是用这样的代码尝试这个,其中drawing_image只是图像的一个url。

var outlineImage = new Image();
outlineImage.crossOrigin = '';
outlineImage.src = drawing_image;
outlineImage.onload = function() 
  var canvas = document.getElementById('explain_canvas');
  var context = canvas.getContext("2d");
  context.drawImage(outlineImage, 10, 10, 600, 150);

但这并没有发送原始标头。所以我想我会尝试通过 jquery 进行 ajax 调用

var outlineImage = new Image();
$(outlineImage).attr('crossOrigin', '');
$.ajax(
    type: 'get',
    url : drawing_image,
    contentType: 'image/png',
    crossDomain: 'true',
    success: function() 
        $(outlineImage).attr("src", drawing_image);
    ,
    error: function() 
        console.log('ah crap');
    
);

outlineImage.onload = function() 
 var canvas = document.getElementById('explain_canvas');
 var context = canvas.getContext("2d");

 context.drawImage(outlineImage, 10, 10, 600, 150);

但仍然没有运气。我弄错了吗?该 jquery ajax 是否应该发送原始标头?

我查看了请求标头,这是我在图像上得到的:

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:em2-images.s3.amazonaws.com
Referer:http://localhost:3000/courses/18/quizzes/22/take
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (Khtml, like Gecko) Chrome/23.0.1271.101 Safari/537.11

还有 jquery 错误:

XMLHttpRequest cannot load http://em2-images.s3.amazonaws.com/EM2_LF_A_5_item6.png. Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin.
ah crap

对我来说奇怪的是 jquery 声明了来源,但它不在请求标头中。

这个*** 问题here 表明他想删除原始标头。好吧,他正在做与 jquery ajax 相同的调用并得到它。任何想法为什么我不是?

如果我重新加载页面,它会抓取缓存的图像并正常加载(请注意原始标头)并调用 toDataURL() 就好了。在我清除缓存后,在图像被缓存之前,第一次加载将无法正常工作。

我开始怀疑 Rails 是否对它做了什么,但我不知道它会如何,因为这是一个 ajax 调用。但是谁知道呢,有人知道 Rails 是否可以做到这一点?

我已经在不同平台上的几个浏览器中尝试过这个。 Chrome、Firefox、Safari、IE 9 和 10。在我的 Mac、PC 和 iPhone 上。他们中的任何一个都没有骰子。

-谢谢-

【问题讨论】:

【参考方案1】:

经过一番绞尽脑汁,我终于弄明白了为什么我的浏览器没有发送原始标头。

首先是一点背景。这是针对 LMS 的,是测验的一部分。当教师编写测验时,他们将问题文本和图像添加到绘图画布中,供学生用绘图解释他们的答案。

您可以猜到,该图像首先被加载。它在学生视图中隐藏,我从该图像中获取 src url,并尝试使用 javascript 将其放入 canvas 元素中。

问题是第一次加载图像时,它没有使用 crossorigin 属性加载。因此没有原始标题。并且当画布元素尝试加载图像时,它被缓存而没有原始标题。当它试图让 cors 运行时,它会呕吐。在我看来,这可能是所有浏览器都需要修复的错误。但也许不是。

因此,简而言之,在执行 cors 时,请确保图像的第一次加载带有 crossorigin 属性以包含原始标头。等我……

是的,是时候重构了...

【讨论】:

谢谢!一旦我知道发生了什么,我设法通过在 url 中添加一个小的缓存清除 GET 属性来解决这个问题。 必须为那些仍然卡住的人添加一些东西。您的答案是正确的,但是在获取缓存资源时,第二次相同的图像,它删除了源头。因此,如果您需要缓存图像,请将其存储在 javascript 中,并且不要再次尝试请求它。我发现我试图提高效率的做法是在缓存项目上抛出错误。 啊,伙计!你救了我的星期五!这种行为相当麻烦。 有一种简单的方法可以解决它:对后续请求使用缓存断路器。像这样:http://mybucket.s3.aws.com/img.jpg?t=12345。其中12345 是每次调用的随机字符串 uniq。这将强制浏览器忽略缓存并执行正确的服务器请求。 现在是 2020 年,它仍然发生在 Chromium/Chrome/Brave 中。在 Firefox/Safari 中运行良好【参考方案2】:

我收到了这个 CORS 错误,并且在服务器端没有发送原始标头。

我的问题是我在图像标签中设置了crossOrigin = Anonymous。删除它为我解决了问题,并且 CORS 错误消失了。

【讨论】:

以上是关于我所有的浏览器都没有发送原始标头的主要内容,如果未能解决你的问题,请参考以下文章

没有 Location 标头的 301 http 响应

原始 http 服务器:发送图像问题

使用 java servlet 在重定向响应中丢失 HTTP 自定义标头

Auth 标头未与 GET 请求一起发送

如何使用 Go/WASM 获取所有标头和 cookie

使用原始请求标头 C# 在请求正文中发送参数和文件