Skip to content

Instantly share code, notes, and snippets.

@xieyuschen
Last active December 28, 2020 13:32
Show Gist options
  • Save xieyuschen/695de69b208bc187316d09360071c671 to your computer and use it in GitHub Desktop.
Save xieyuschen/695de69b208bc187316d09360071c671 to your computer and use it in GitHub Desktop.
Cannot make a request to certain api for CORS

Cross Origin Resource Share

之前遇到的问题

之前的跨域问题很意外,hmm,我对这个东西还没有什么概念。情况是这样的,首先我写了几个api,然后监听8080端口。使用nginx进行代理,将对80访问的内容和对432访问的内容全部转发到127.0.0.1:8080去。然后前端在发请求的时候就遇到了跨域的问题。 解决方案:在nginx里面加一个同意跨域的设置 Access-Control-Allow-Origin:*。即可解决。

简单的提几个问题出来:

  • 跨域请求被阻塞发生在什么时候? 是nginx完成的阻塞,还是程序本身的阻塞

回答 阻塞由浏览器来完成,即正常发送请求,后端正常给予响应,但响应结果被浏览器拦截

也即,阻塞发生在浏览器处理响应的阶段

  • 为什么会有跨域这个概念 一个域名的网页去请求另外一个域名的网页。
  • nginx转发的时候为什么会有跨域的概念 之前在使用Go编写后端代码的时候出现了跨域的问题,所以就需要来了解下什么是Cors。

一些概念

  • Cross-Origin Resource Sharing
      Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources.
    For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy.
    The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser. 注意这里CORS其实是server能不能从浏览器读取到信息。

协议、域名、端口全部相同才算同一域。同一域名下的子域名进行交互,也会出现跨域问题。

CORS 的使用得益于 HTTP-1.1 协议版本的推广的大面积使用,它由一系列传输的HTTP头组成,这些HTTP头有两个作用:
1:用于阻止还是允许浏览器向其他域名发起请求;
2:用于接受还是拒绝其他域名返回的响应数据;

自问自答:

  • HTTP头是谁添加的?
    在发生跨域访问的时候,浏览器首先会发送一个OPTIONS的请求,获取到跨域的相关信息,这个过程叫做preflight。然后在基于之前的结果发送正式的请求。
  • 1:用于阻止还是允许浏览器向其他域名发起请求 即在preflight过程之后如果获取到的标准和实际的请求有冲突,那么这个请求会直接被浏览器所拒绝,不影响进行跨域操作。
  • 2:用于接收还是拒绝其他域名返回的响应数据 结束与拒绝的响应主题为浏览器,即浏览器根据服务器端响应信息决定接受还是拒绝这些数据。
  • 如何进行控制访问?

首先看一个例子,我从gist首页跳转到Github profile,打开f12看内容,关于请求头比较重要的内容如下:

-->General
Request URL: https://github.com/Xieyuschen
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:4780
Referrer Policy: strict-origin-when-cross-origin


--->Request Header
Referer: https://gist.github.com/

--->Response Header
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin


里面有一些关于CORS的内容,那么就让我看下Cors是如何工作的。去读一读文档.

浏览器拦截

跨域这个概念准确来说是浏览器层面(是否可以这么理解)的,因为对一个(跨域的)请求来说发送的请求和响应都可以正常工作。但是浏览器把它过滤掉了。这样就产生一个问题,一大部分Http请求拥有副作用,尽管浏览器进行了拦截,但是http请求的更改已经在服务端生效。

  • 概念辨析
    我这里说的浏览器拦截,指的是什么?目前我说的应该是浏览器将请求的返回内容拦截,也就是请求发了出来,然后也得到了响应,但是浏览器把这个响应给过滤掉了,拒绝接受相应的服务(不一定对嗷)。
    看这段内容:

Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other than GET, or POST with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with the HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request.
Servers can also inform clients whether "credentials" (such as Cookies and HTTP Authentication) should be sent with requests.

即浏览器首先对这个请求做处理,这个过程叫做preflight,这个过程通过http options这个请求从后端获取到服务端支持的方法,然后等服务器批准之后再发送实际的请求。

一些Demo

Simple Request-->不因跨域被浏览器过滤的请求

这里写了基本的要求,客户端发出一个跨域资源的请求,然后在服务器端处理完返回的时候,加上一个Access-Control-Allow-Origin: *。这样浏览器接收到请求之后,就不需要考虑跨域的问题了。

Preflight Request

  1. first sends an HTTP request using the OPTIONS method to the resource on the other origin, in order to determine if the actual request is safe to send. 第一步发一个类型为OPTIONS的请求,然后可以获取到一些信息。然后浏览器根据这些信息进行preflight。
  2. Preflight完成之后,就发送真正的请求。 顺便提一句,是谁给OPTIONS请求返回对应内容的呢,我猜需要在程序上加一个中间件才可以。
  • 好家伙,对husthole.pivotstudio.cn发个OPTIONS的请求,直接405
<html>

<head>
	<title>405 Not Allowed</title>
</head>

<body bgcolor="white">
	<center>
		<h1>405 Not Allowed</h1>
	</center>
	<hr>
	<center>nginx/1.14.1</center>
</body>

</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment