漏洞赏金猎人笔记-GraphQL-III

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 前面介绍了query、mutation这两种类型的操作,今天将要介绍最后一种类型的操作:subscription



前言


前面介绍了query、mutation这两种类型的操作,今天将要介绍最后一种类型的操作:subscription

这里对这三种类型的操作做一个简单的总结:

  • query 查询:获取数据,比如查找,CRUD 中的 R
  • mutation 变更:对数据进行变更,比如增加、删除、修改,CRUD 中的 CUD
  • substription 订阅:当数据发生更改,进行消息推送

此外,这三种类型都需要由解析函数 Resolver 来提供数据,比如

query {
  hi
}

那么同名的解析函数resolver(一般也是写在后端)应该是这样的

Query: {
  hi (parent, args, context, info) {
    return ...
  }
}

解析函数接受四个参数,分别为

  • parent:当前上一个解析函数的返回值
  • args:查询中传入的参数
  • context:提供给所有解析器的上下文信息
  • info:一个保存与当前查询相关的字段特定信息以及 schema 详细信息的值

解析函数的返回值可以是一个具体的值,也可以是 Promise 或 Promise 数组。

此外还需要知道Schema这个文件:

它定义了字段的类型、数据的结构,描述了接口数据请求的规则,当我们进行一些错误的查询的时候 GraphQL 引擎会负责告诉我们哪里有问题,和详细的错误信息,对开发调试十分友好。

Schema一般使用一个简单的强类型模式语法,称为模式描述语言(Schema Definition Language, SDL)

# src/schema.graphql
# Query 入口
type Query {
    hello: String
    users: [User]!
    user(id: String): [User]!
}
# Mutation 入口
type Mutation {
    createUser(id: ID!, name: String!, email: String!, age: Int,gender: Gender): User!
    updateUser(id: ID!, name: String, email: String, age: Int, gender: Gender): User!
    deleteUser(id: ID!): User
}
# Subscription 入口
type Subscription {
    subsUser(id: ID!): User
}
type User implements UserInterface {
    id: ID!
    name: String!
    age: Int
    gender: Gender
    email: String!
}
# 枚举类型
enum Gender {
    MAN
    WOMAN
}
# 接口类型
interface UserInterface {
    id: ID!
    name: String!
    age: Int
    gender: Gender
}

这里的 Schema 文件(这个文件一般写在后端)从 Query、Mutation、Subscription 入口开始定义了各个对象类型或标量类型,这些字段的类型也可能是其他的对象类型或标量类型,组成一个树形的结构,而用户在向服务端发送请求的时候,沿着这个树选择一个或多个分支就可以获取多组信息。


正文


这里主要通过一个实例来理解,先看个图来理解大体上的一个逻辑:

26.png

通过订阅这样的一个操作在服务端注册了了一个订阅查询,如果服务端有对应的更新,就会触发这个所订阅的查询,最后会在客户端实时更新。

下面通过一个例子来理解一下Subscription:

当前端发起订阅请求之后,如果后端发现数据改变,可以给前端推送实时信息。

Schema文件:

# Subscription 入口
type Subscription {
    subsUser(id: ID!): User
}
type User {
    id: ID!
    name: String!
    age: Int
    email: String!
}

对应resolver:

import Db from'../db'
const { PubSub, withFilter } = require('apollo-server')
const pubsub = new PubSub()
const USER_UPDATE_CHANNEL = 'USER_UPDATE'
exportdefault {
    Mutation: {
        updateUser: (parent, { id, name, email, age }) => Db.user({ id })
            .then(existUser => {
                if (!existUser)
                    thrownewError('没有这个id的人')
                return existUser
            })
            .then(() => Db.updateUser({ id, name, email, age }))
            .then(user => {
                pubsub.publish(USER_UPDATE_CHANNEL, { subsUser: user })
                return user
            })
    },
    Subscription: {
        subsUser: {
            subscribe: withFilter(
                (parent, { id }) => pubsub.asyncIterator(USER_UPDATE_CHANNEL),
                (payload, variables) => payload.subsUser.id === variables.id
            ),
            resolve: (payload, variables) => {
                console.log('🚢 接收到数据:', payload)
            }
        }
    }
}

这里的 pubsub 是 apollo-server 里负责订阅和发布的类,它在接受订阅时提供一个异步迭代器,在后端觉得需要发布订阅的时候向前端发布 payload。withFilter 的作用是过滤掉不需要的订阅消息

我们发布一个订阅请求:

# 请求
subscription subsUser($id: ID!) {
  subsUser(id: $id) {
    id
    name
    age
    email
  }
}
# 参数
{ "id": "2" }

用刚刚的数据更新操作来进行一次数据的更改,然后我们将获取到并打印出 pubsub.publish 发布的 payload,这样就完成了数据订阅。

全文完结。


参考

https://www.apollographql.com/docs/react/data/subscriptions/

https://dgraph.io/blog/post/how-does-graphql-subscription/

https://github.com/apollographql/docs-examples/blob/main/apollo-server/v3/subscriptions-graphql-ws/src/index.ts#L14


目录
相关文章
|
7月前
|
安全 JavaScript 前端开发
赏金猎人必学站点(梯外)
赏金猎人必学站点(梯外)
|
存储 算法 搜索推荐
外网疯传!字节大佬闭关三月撰写的数据结构与算法笔记遭恶意开源
数据结构与算法的定义 数据结构(data structure)是带有结构特性的数据元素的集合,它研究的是数据的逻辑结构的相互关系,并对这种结构定义相适应的运算,,确保经过这些运算以后所得到的新结构仍保持原来的结构类型。简而言之,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。“
55 0
|
JSON 安全 C语言
黑客需要用到的Python技术?
黑客需要用到的Python技术?
|
SQL Oracle 安全
PortSwigger之SQL注入实验室笔记(一)
PortSwigger之SQL注入实验室笔记
341 0
PortSwigger之SQL注入实验室笔记(一)
|
SQL 安全 Oracle
PortSwigger之SQL注入实验室笔记(二)
PortSwigger之SQL注入实验室笔记
342 0
PortSwigger之SQL注入实验室笔记(二)
|
SQL 安全 网络协议
PortSwigger之SQL注入实验室笔记(三)
PortSwigger之SQL注入实验室笔记
208 0
PortSwigger之SQL注入实验室笔记(三)
|
JSON 安全 前端开发
漏洞赏金猎人笔记-GraphQL-I
为了方便理解,这里从一个例子出发来理解GraphQL 通常情况下,当你想获取有关书籍和作者的详细信息时,用REST API的风格写为:
241 0
漏洞赏金猎人笔记-GraphQL-I
|
安全 API 网络架构
漏洞赏金猎人笔记-GraphQL-II
上一节我们学习了GraphQL的一些基础知识,本文继续深入研究,从对比的角度来切入,方便读者理解. Mutation 在GraphQL中,只有两种类型的操作,就是queries 和 mutations. 如果说query类似于REST中的GET操作,那么Mutation就好比REST中的DELETE, PUT,PATCH方法,笔者用一句简单的话来概括一下: query用来查询服务端的数据,而mutation用来修改服务端的数据
238 0
漏洞赏金猎人笔记-GraphQL-II
|
数据采集 域名解析 XML
漏洞猎人赏金笔记-如何编写Bug Bounty自动化脚本
前言 本文原文作者为@pry0cc,本文主要是对原文相关内容的提炼以及笔记,出于易读性考虑,笔者对很多地方做了一定量的注释或者删改(因为原文中的脚本存在一定问题)。 本文主要讲解的是经典的自动化信息搜集以及数据处理和漏洞扫描的流程.
575 0
漏洞猎人赏金笔记-如何编写Bug Bounty自动化脚本