RESTful API 是一种基于 REST(Representational State Transfer,表现层状态转移)架构风格的 API 设计规范,它的核心思想是资源(Resource)和 HTTP 方法(Method)构成的组合来实现对资源的操作。
具体来说,RESTful API 通过 HTTP 方法来对资源进行操作,通常使用以下 4 种 HTTP 方法:
GET:获取资源
POST:创建资源
PUT:更新资源
DELETE:删除资源
同时,RESTful API 还应该满足以下几点要求:
每个资源都有一个唯一的标识符(URI)来表示资源的位置
所有的操作都是无状态的,也就是不依赖于之前的操作状态
数据的表示应该使用标准的数据格式,如 JSON 或 XML
安全性方面需要考虑如身份认证和访问授权等问题
通过遵循 RESTful API 的设计规范,可以使 API 的设计更加合理、清晰,并且易于维护和扩展。
当然,以下是一些常见的 RESTful API 接口规范:
获取资源列表:GET /resources
获取指定 ID 资源:GET /resources/:id
创建资源:POST /resources
更新指定 ID 资源:PUT /resources/:id
删除指定 ID 资源:DELETE /resources/:id
其中 :id
表示 URL 参数,可以是任意字符串。另外,请求和响应的数据格式通常使用 JSON,具体如下:
请求方式:GET
请求 URL:/resources
请求参数:无
响应状态码:
200 OK - 成功获取资源列表
404 Not Found - 未找到资源列表
响应数据格式:
{
"data": [
{
"id": 1,
"name": "Resource 1",
"description": "Description 1"
},
{
"id": 2,
"name": "Resource 2",
"description": "Description 2"
}
]
}
请求方式:GET
请求 URL:/resources/:id
请求参数:无
响应状态码:
200 OK - 成功获取指定 ID 资源
404 Not Found - 未找到指定 ID 资源
响应数据格式:
{
"data": {
"id": 1,
"name": "Resource 1",
"description": "Description 1"
}
}
请求方式:POST
请求 URL:/resources
请求参数:
{
"name": "Resource 3",
"description": "Description 3"
}
响应状态码:
201 Created - 成功创建资源
400 Bad Request - 请求参数错误
响应数据格式:
{
"data": {
"id": 3,
"name": "Resource 3",
"description": "Description 3"
}
}
除了 RESTful 设计规范之外,还有一些其他的设计规范,例如 SOAP、GraphQL、gRPC 等。这些规范都有其优缺点,适用于不同的场景和需求。
SOAP 是一种基于 XML 的通信协议,它使用了一些标准的协议,如 HTTP、SMTP、TCP、UDP 等,用于在 Web 上进行数据交换。它通过 WSDL(Web Services Description Language)来描述 Web 服务接口,因此具有较强的规范性和可扩展性。SOAP 对于安全性和事务处理的支持较好,但其缺点是过于冗长和繁琐,不易阅读和编写。
GraphQL 是 Facebook 开源的一种数据查询语言和 API 设计规范,它可以让客户端查询需要的数据而不会浪费网络带宽和服务器资源。GraphQL 的优点是可以在一次请求中获取多个数据,避免了 RESTful 接口中多次请求数据的问题。GraphQL 还支持多版本和类型检查等功能。但是,GraphQL 适用于较为复杂的场景,对于简单的数据查询,使用 RESTful 接口可能更为方便。
gRPC 是 Google 开源的一种高性能、跨语言的远程过程调用(RPC)框架,它使用了 Protobuf 作为序列化和反序列化的协议。gRPC 的优点是高性能、跨语言支持、自动生成代码等。但是,它的缺点是比较复杂,需要进行额外的学习和使用。
综上所述,不同的规范适用于不同的场景和需求。在选择时需要根据实际情况进行综合考虑。
GraphQL是一种由Facebook开发的查询语言和运行时环境,用于构建API,并提供强类型、可扩展和可文档化的数据查询接口。
与RESTful API相比,GraphQL的主要优势是:
更少的网络请求:GraphQL支持客户端一次性请求多个资源,而不是像RESTful API那样需要多个请求。
精确获取数据:GraphQL允许客户端精确指定需要获取的数据,而不是像RESTful API那样需要获取整个资源的所有数据。
强类型定义:GraphQL使用类型定义来描述API中的数据模型,可以避免许多类型错误和错误处理问题。
下面是一个简单的GraphQL查询示例:
query {
user(id: 123) {
name
email
posts(limit: 10) {
title
content
}
}
}
这个查询请求将返回id为123的用户的姓名、电子邮件和最近10篇帖子的标题和内容。
可以看到,GraphQL的查询语言相对于RESTful API的HTTP请求更加精细和高效。但是,在使用GraphQL时需要花费更多的精力来规划和设计API架构,因此在小型项目或小型API中使用可能会过度复杂化。
GraphQL 既是一种设计规范,也是一种查询语言。
作为一种设计规范,GraphQL 定义了一组基本概念和规则,以便客户端和服务器之间能够定义和执行对于数据的查询和变更操作。这些基本概念包括:对象类型(Object Types)、字段(Fields)、参数(Arguments)以及查询(Query)、变更(Mutation)和订阅(Subscription)等操作类型。
作为一种查询语言,GraphQL 可以让客户端定义它们需要的数据,而不需要预定义复杂的多个接口或者对已有的 RESTful API 进行重构。通过发送一个 GraphQL 查询,客户端可以获取精确的需要的数据,避免了浪费带宽和资源的问题。
下面是一个 GraphQL 查询的例子:
query {
movie(id: 1) {
title
director
releaseDate
actors {
name
age
}
}
}
在这个例子中,我们查询了一个名为 “movie” 的对象,指定了 id 参数为 1,并要求返回电影的标题、导演、发行日期以及演员的姓名和年龄等信息。根据这个查询,服务端可以返回一个包含所有请求数据的 JSON 对象。
是的,如果客户端希望使用 GraphQL 来获取数据,后端接口需要提供支持 GraphQL 的 API。这意味着后端需要编写相应的 GraphQL schema,并实现相关的 resolver 函数来获取和处理数据。如果后端原先是基于 RESTful 接口实现的,那么需要对原有接口做一定的改造,以符合 GraphQL 的要求。
GraphQL 的请求和响应格式与传统的 RESTful 接口有很大的不同。RESTful 接口通常会返回整个资源的完整信息,而 GraphQL 的请求可以精确指定需要返回的字段,避免了资源浪费。因此,如果后端想要提供 GraphQL 支持,需要重新设计 API 的返回格式,以支持 GraphQL 的请求和响应格式。
总之,使用 GraphQL 需要后端和前端共同配合,后端需要提供支持 GraphQL 的接口,前端需要使用相应的客户端库来发起 GraphQL 请求,并处理返回结果。
可以。在浏览器控制台的 Network 标签页中,可以看到 GraphQL 请求的信息,包括请求的 URL、请求方法、请求头、请求体等。同时,也可以查看响应的信息,包括响应状态码、响应头、响应体等。在响应体中,可以看到 GraphQL 返回的数据,以及对应的字段和类型信息。
看控制台的报错应该可以看到,是由于第三方页面在响应头(response header)里设置了Content-Security-Policy(简称CSP)引起的。那么什么是CSP呢?
Content-Security-Policy
HTTP 响应头
Content-Security-Policy
允许站点管理者控制用户代理能够为指定的页面加载哪些资源。除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。这将帮助防止跨站脚本攻击(Cross-Site Script
)(XSS (en-US))。reference:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy
也就是说第三方网页为了防止自己被别人加载了自己的网页,可以设置用户加载时候是否跟当前地址是一个主域名等规则限制。设置规则例如可以有:
default-src:为其他取指令提供备用服务 fetch directives。
connect-src:限制能通过脚本接口加载的 URL。
……
等等规则。
那么,有解吗?基本是无解的,不要想着强行绕过去了。
因为登录完后一般会由服务端种植cookie,但是set-cookie有一个默认属性SameSite=Lax。
Lax
: 这意味着 cookie 不会在跨站请求中被发送,如:加载图像或 frame 的请求。但 cookie 在用户从外部站点导航到源站时,cookie 也将被发送(例如,跟随一个链接)。这是SameSite
属性未被设置时的默认行为。
这也就是说,因为iframe加载的页面和当前网站存在跨站行为,所以登录的cookie不会被携带。那么如何解决呢?
可以通过chrome插件的方式来修改cookie的SameSite属性,将其设置为None。因为Chrome浏览器插件不受跨站跨域的限制,所以对于本地调试的场景,可以通过安装相关cookie透传的插件来解决。
在设置这一属性值时,必须同时设置 Secure
属性,就像这样:SameSite=None; Secure
。
备注: 与 SameSite Cookie 相关的标准作了如下变动:
SameSite
属性未被指定时,其默认行为是SameSite=Lax
。在过去,若未指定,所有的 cookie 均会被发送。现在,携带
SameSite=None
属性的 cookie 必须同时设置Secure
属性(换句话说,其仅能用于安全上下文)来自同一域的 cookie 若使用了不同的协议(
http:
或HTTPS:
),将不再被视为来自同一站点。参见浏览器兼容性表以了解不同浏览器的实线情况(行:“
SameSite
: Defaults toLax
”、“SameSite
: Secure context required”和“SameSite
: URL scheme-aware (“schemeful”)”)。
强缓存优先级:Cache-Control > Expires。Expires的格式是一个日期(例如Sat, 11 Jul 2020 06:26:27 GMT),这容易被本地时间影响,造成缓存冲突。Cache-Control的格式是:max-age=604800,用有限时间来控制。
协商缓存优先级:ETag > Last-Modified。
Last-Modified表示本地文件最后修改日期,浏览器会在请求 header加上If-Modified-Since(上次返回的Last-Modified的值),询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。
Etag就像一个指纹,资源变化都会导致ETag变化,跟最后修改时间没有关系,ETag可以保证每一个资源是唯一的 If-None-Match的header会将上次返回的Etag发送给服务器,询问该资源的Etag是否有更新,有变动就会发送新的资源回来
注:Etag优先级是高于Last-Modifed的,所以服务器会优先验证Etag 具体为什么要用ETag,主要出于下面几种情况考虑:
一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新获取;
某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
某些服务器不能精确的得到文件的最后修改时间。