后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载导读本文围绕 GraffleSimple GraphQL Client for JavaScriptHTTP 传输中的methodMode: getReads方法模式展开讲解如何让 query / subscription 等读类型操作通过 HTTP GET 发送、同时让 mutation 写操作继续走 HTTP POST 的完整配置方法。读完本文你将掌握methodMode两种取值post/getReads的语义差异、GET 模式下请求参数如何编码进 URL 搜索参数、底层方法选择逻辑以及如何借助 anyware 中间件验证最终发出的请求。本文核心素材来自仓库中的 method-get 示例文档、示例源码 及其 输出记录底层实现参考 TransportHttp 扩展源码 与 HTTP 编码实现。一、getReads模式解决什么问题HTTP 传输默认情况下所有请求都通过 HTTP POST 发送这也是 TransportHttp 配置默认值 中methodMode: post的含义。但在某些场景下我们希望读操作query、subscription走 HTTP GET从而获得 GET 的缓存友好、可分享 URL 等特性同时保持写操作mutation走 POST。Graffle 的methodMode配置提供了两种取值见 MethodMode 常量定义取值行为post默认所有操作均通过 HTTP POST 发送请求体为 JSONgetReads读类型操作query、subscription通过 HTTP GET 发送写类型操作mutation仍通过 HTTP POST 发送二、最小可运行示例以下完整示例来自 examples/10_transport-http/transport-http_method-get.ts它创建一个 Graffle 客户端配置methodMode: getReads并通过 anyware 中间件打印出每次请求的完整信息import { Graffle } from graffle import { publicGraphQLSchemaEndpoints, show } from ../$/helpers.js const graffle Graffle .create() .transport({ url: publicGraphQLSchemaEndpoints.Pokemon, methodMode: getReads, // [!code highlight] headers: { tenant: nano }, }) .anyware(async ({ exchange }) { show(exchange.input.request) return await exchange() }) // The following request will use an HTTP POST method because it is // using a mutation type of operation. await graffle.gql(mutation { addPokemon(attack:0, defense:0, hp:1, name:Nano, type: grass) { name } }).$send() // The following request will use an HTTP GET method because it // is using a query type of operation. await graffle.gql(query { pokemonByName(name: Nano) { hp } }).$send()其中publicGraphQLSchemaEndpoints.Pokemon来自 examples/$/helpers.ts默认指向http://localhost:3000/graphql也可以通过环境变量POKEMON_SCHEMA_URL覆盖。示例中.anyware()的作用是在请求发出前拦截并打印exchange.input.request即最终构造的 Request 对象这是验证方法模式是否生效的最直接手段。三、输出验证mutation 走 POSTquery 走 GET示例运行后产生的实际输出保存在 examples/outputs/10_transport-http/transport-http_method-get.output.txt两份输出清晰地展示了两种请求的差异。第一份输出对应 mutationaddPokemon虽然methodMode是getReads但请求仍然走 POST且请求体为 JSON{ methodMode: getReads, headers: Headers { accept: application/graphql-responsejson; charsetutf-8, application/json; charsetutf-8, content-type: application/json, tenant: nano }, method: post, url: { _tag: url, value: URL { href: http://localhost:3000/graphql, ... } }, body: {query:mutation { addPokemon(attack:0, defense:0, hp:1, name:\\Nano\\, type: grass) { name } }} }第二份输出对应 querypokemonByName请求走 GET且 GraphQL 文档被编码进 URL 搜索参数query{ methodMode: getReads, headers: Headers { accept: application/graphql-responsejson; charsetutf-8, application/json; charsetutf-8, tenant: nano }, method: get, url: { _tag: url, value: URL { href: http://localhost:3000/graphql?queryquery%7BpokemonByName%28name%3A%22Nano%22%29%7Bhp%7D%7D, ... searchParams: URLSearchParams { query query { pokemonByName(name: Nano) { hp } } }, } } }从两份输出可以总结出 GET / POST 请求的差异method 字段mutation 为postquery 为get请求头POST 请求带accept与content-type: application/jsonGET 请求只带accept没有content-type因为请求体为空载荷位置POST 请求将 GraphQL 文档放在 JSON body 中GET 请求将 GraphQL 文档作为query搜索参数拼接到 URL 上URL 形态GET 请求的 URL 会带?query...搜索串如http://localhost:3000/graphql?queryquery%7BpokemonByName...。四、底层原理方法选择与载荷编码4.1 方法选择的判定逻辑getReads并不是简单地读操作全走 GET其底层判定逻辑位于 TransportHttp.ts 的 run 函数const methodMode input.transport.methodMode const requestMethod methodMode MethodMode.post ? post : GraphqlKit.Schema.OperationType.LookupToAccessKind[operationType] read ? get : post从源码结构可以看出若methodMode为post则一律使用 POST若methodMode为getReads则根据操作的访问类型AccessKind判断读操作read即 query / subscription用 GET写操作write即 mutation仍用 POSToperationType从请求的 operation 字段解析而来Str.is(input.request.operation)判断是字符串还是结构化对象。4.2 GET 的搜索参数编码GET 请求的载荷编码由 getRequestEncodeSearchParameters 实现它把 GraphQL 请求编码为 URL 搜索参数对象export const getRequestEncodeSearchParameters (request: RequestConfig): Recordstring, string { return { query: request.query, ...(request.variables ? { variables: JSON.stringify(request.variables) } : {}), ...(request.operationName ? { operationName: request.operationName } : {}), } }也就是说GET 模式下支持三个搜索参数queryGraphQL 文档、variables变量JSON 序列化、operationName操作名仅在存在时才编码。随后这些搜索参数会通过Http.SearchParams.appendAll/appendAllToPath拼接到 URL 上TransportHttp.ts。4.3 POST 的 JSON body 编码POST 请求的载荷由 postRequestEncodeBody 实现将query、variables、operationName序列化为 JSON 字符串作为请求体。4.4 请求头差异两类请求的默认请求头也由 HTTP 编码实现 区分export const postRequestHeadersRec { accept: ACCEPT_REC, content-type: CONTENT_TYPE_REC, } export const getRequestHeadersRec { accept: ACCEPT_REC, }其中ACCEPT_REC为application/graphql-responsejson; charsetutf-8, application/json; charsetutf-8CONTENT_TYPE_REC为application/json均遵循 GraphQL Over HTTP 规范 的媒体类型约定对应代码注释见 http/__.ts。这正是示例输出中 GET 请求没有content-type头的原因。五、methodMode 的三种配置途径与优先级methodMode与url、headers、raw一样属于 TransportHttp 的配置项见 ConfigurationInput 定义可通过三种途径配置见 TransportHttp 文档构造函数中.transport({ methodMode: getReads, ... })with方法中动态切换配置扩展栈中通过扩展追加配置。配置优先级从高到低为扩展栈后注册的扩展优先→with配置 → 构造函数配置其中raw配置优先级高于transport下其他平级属性。5.1 显式配置 POST如果需要显式恢复默认的 POST 行为可以显式声明import { Graffle } from graffle Graffle .create() .transport({ methodMode: post, })5.2 显式配置 getReadsimport { Graffle } from graffle Graffle .create() .transport({ methodMode: getReads, })六、url 与 headers 配置细节在getReads模式下url的配置同样支持多种形态TransportHttp.ts绝对 URL 字符串https://api.example.com/graphql相对路径字符串/api/graphql、./graphql、../graphql浏览器环境或框架增强 fetch 场景下有用URL 对象需要留意的是Node.js 原生 fetch 不支持相对 URL相对路径仅在浏览器或提供增强 fetch 的框架如 SvelteKit中有效。配置解析在配置期即完成校验parseURLInput会在 URL 非法时提前抛出错误避免运行时才暴露问题。headers采用合并策略Http.Headers.mergeInitWithStrategyMerge见 TransportHttp.ts且若某个 header 被赋空字符串值会删除先前设置的该 header。七、注意事项methodMode: getReads只影响 HTTP 方法选择不会改变操作本身的性质mutation 永远走 POST这是 示例文档 与源码共同确认的行为GET 模式下 GraphQL 文档会完整出现在 URL 中若文档包含敏感信息请结合业务场景评估是否适合使用 GETtransport.raw可以直接透传原生fetch配置如{ mode: cors }但由于没有护栏若在raw.method中设置PATCH之类的值会覆盖methodMode的判定结果产生不符合 GraphQL Over HTTP 规范的请求TransportHttp 文档 中的 Raw 一节有明确提醒示例输出验证方式可复用通过.anyware()打印exchange.input.request即可在任意环境中确认方法模式是否按预期生效。八、延伸阅读TransportHttp 扩展文档完整的配置说明、相对 URL 用法、raw 配置与 ware 钩子说明TransportHttp 实现源码methodMode判定、URL 解析、请求构造的完整逻辑HTTP 编码与解码实现GET 搜索参数编码、POST body 编码、请求头与响应解析method-get 示例输出示例实际运行产生的请求快照同目录下其他 HTTP 传输示例raw、abort、headers 等可对照理解 TransportHttp 的完整能力面。赞分享后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载相关推荐cpp-httplib 流式上传实战用 ContentProviderWithoutLength 发送 HTTP Chunked 传输正文cpp httplib 流式上传实战用 ContentProviderWithoutLength 发送 HTTP Chunked 传输正文 本文基于 cpp后端网络Graffle 请求取消实战使用 AbortController 中断 GraphQL HTTP 请求Graffle 请求取消实战使用 AbortController 中断 GraphQL HTTP 请求 本文讲解如何在 Graffle一个极简、可扩展、类型后端Graffle多传输支持详解HTTP与内存传输的最佳实践Graffle多传输支持详解HTTP与内存传输的最佳实践 Graffle作为一款现代化的GraphQL客户端其最强大的特性之一就是 多传输支持 。无论您是需后端上一篇GeoLibre 实时协作全解析基于 Cloudflare Durable Object 的会话同步协议、权限模型与自托管部署指南下一篇3大技术突破开源散热控制器如何彻底改变Dell笔记本性能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考