概述

一直在寻找一个好用的 graphql 服务, 之前使用比较多的是 prisma, 但是 prisma1 很久不再维护了, 而 prisma2 仅仅就是一个 ORM, 不是一个完备的系统.

后来, 朋友介绍了一个 graphql 引擎 hasura, 这个是完备的系统,

不仅提供 UI 来创建数据库和表结构. 还有相应的权限控制, 也有对接第三方服务的 Events, 对数据更多控制的 Actions.

为了使用其 graphql 接口, 同样, 和之前使用 prisma 时一样, 用 golang 的 gin 框架作为 gateway, 对 graphql 接口做一层反向代理.

数据的操作基本都使用 hasura 的 graphql 接口, 逻辑比较复杂的, 或者是文件 上传/下载 相关的, 利用 gin 开发 restful 接口.

反向代理代码

对请求的处理

  1. 路由部分

    1  r := gin.Default()
    2 apiV1 := r.Group("/api/v1")
    3
    4 // proxy hasura graphql
    5 authRoute.POST("/graphql", ReverseProxy())
  2. 处理请求的 body, 并转发到 hasura 上

     1  func ReverseProxy() gin.HandlerFunc {
    2
    3 u, err := url.Parse("your hasura graphql endpoint")
    4 if err != nil {
    5 log.Fatal(err)
    6 }
    7
    8 return func(c *gin.Context) {
    9 director := func(req *http.Request) {
    10 req.URL.Scheme = u.Scheme
    11 req.URL.Host = u.Host
    12 req.URL.Path = u.Path
    13 delete(req.Header, "Authorization")
    14 delete(req.Header, "Accept-Encoding")
    15
    16 req.Header.Set("Content-Type", "application/json; charset=utf-8")
    17 fmt.Printf("req header: %v\n", req.Header)
    18 }
    19
    20 body, err := c.GetRawData()
    21 if err != nil {
    22 fmt.Printf("get body raw data: %s\n", err)
    23 }
    24
    25 fmt.Printf("%s\n", string(body))
    26
    27 c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
    28
    29 proxy := &httputil.ReverseProxy{Director: director}
    30 proxy.ModifyResponse = util.RewriteBody
    31 proxy.ServeHTTP(c.Writer, c.Request)
    32 }
    33 }

    这里获取了请求的 body, 但是没有做任何处理, 直接转发给 hasura. 这里可以根据实际情况加入自己的处理.

对返回值的处理

请求的问题解决之后, 就是返回值的处理, 之所以要对返回值进行处理, 是因为 hasura 直接返回的值没有我们自定义的一些 code.

所以需要对返回值进行一些包装, 也就是上面代码中的 RewriteBody

 1  func RewriteBody(resp *http.Response) error {
2 b, err := ioutil.ReadAll(resp.Body)
3 if err != nil {
4 return err
5 }
6
7 err = resp.Body.Close()
8 if err != nil {
9 return err
10 }
11
12 var gResp GraphqlResp
13 var rResp RestResp
14
15 err = json.Unmarshal(b, &gResp)
16 if err != nil {
17 return err
18 }
19
20 if gResp.Errors != nil {
21 rResp = RestResp{
22 Code: FAIL,
23 Message: gResp.Errors[0].Message,
24 Data: gResp.Data,
25 }
26 } else {
27 rResp = RestResp{
28 Code: SUCCESS,
29 Message: "",
30 Data: gResp.Data,
31 }
32 }
33
34 nb, err := json.Marshal(&rResp)
35 if err != nil {
36 return err
37 }
38 body := ioutil.NopCloser(bytes.NewReader(nb))
39 resp.Body = body
40 resp.ContentLength = int64(len(nb))
41 resp.Header.Set("Content-Length", strconv.Itoa(len(nb)))
42 return nil
43 }

这样, graphql 接口的返回值也和其他自己写的 restful 接口的返回值格式一致了.

遇到的问题

上面反向代理的代码编写过程中, 遇到一个问题, 弄了解决了大半天才解决. 在请求 graphql 接口时, 始终报这个错误:

invalid character '\x1f' looking for beginning of value

解决方法很简单, 就是上面的这行代码:

1  delete(req.Header, "Accept-Encoding")

hasura的golang反向代理的更多相关文章

  1. golang 反向代理

    服务器 package main import ( "bytes" "encoding/base64" "encoding/json" &q ...

  2. golang 实现HTTP代理和反向代理

    正向代理 package main import ( "fmt" "io" "net" "net/http" " ...

  3. golang http proxy反向代理

    本文介绍golang中如何进行反向代理. 下面例子中, proxy server接收client 的 http request,转发给true server,并把 true server的返回结果再发 ...

  4. golang学习笔记9 beego nginx 部署 nginx 反向代理 golang web

    golang学习笔记9 beego nginx 部署 nginx 反向代理 golang web Nginx 部署 - beego: 简约 & 强大并存的 Go 应用框架https://bee ...

  5. IIS 反向代理 golang web开发

    一. beego 开发编译 bee run 后会编译成 exe文件 编译生成后发布文件结构为 cmd 运行 cd D:/run beegoDemo.exe run 默认配置端口 不能为 80 跟iis ...

  6. aProxy: 带认证授权和权限控制的反向代理

    前段时间很多数据库因为没有做好权限控制暴露在外网被删然后遭勒索的事件,而类似的有些内网的web服务也会被开放到公网并且没有做任何权限控制的,这样也会有一定的风险.所以就决定写篇文章简单介绍一个小工具. ...

  7. Nginx插件之openresty反向代理和日志滚动配置案例

    Nginx插件之openresty反向代理和日志滚动配置案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.openresty介绍 1>.Nginx介绍 Nginx是一款 ...

  8. prisma反向代理

    概要 为什么要做 prisma 的反向代理 反向代理示例(by golang) prisma 服务 gateway 服务 整体流程 认证 反向代理 权限 总结 概要 接触 prisma 有段时间了, ...

  9. Nginx-正反向代理及负载均衡

    目录 正/反向代理 代理的方式 Nginx代理服务支持的协议 代理实战 部署web01 部署Lb01 Nginx代理常用参数 添加发往后端服务器的请求头信息 代理到后端的TCP连接.响应.返回等超时时 ...

随机推荐

  1. 09vuex

    state 大白话:获取state的值 vuex中state数据是响应式的.只要state中数据发生变化.vue组件自动更新. 要想做到响应式 前提:是在mutaion中定义函数修改state值. 最 ...

  2. 关于Vue-Router的那些事儿

    Vue-Router Vu-router是Vue.js的官方路由管理器,方便于构建页面,在我们的使用过程中,一般是在router的index.js文件中配置对应的组件和对应的路径 主要的功能 嵌套路由 ...

  3. leetcode刷题-82.删除排序链表中的重复元素 II

    题目 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4->4->5输出: 1- ...

  4. leetcode刷题-83删除排序链表中的重复元素

    题目 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 实现 # Definition for singly-li ...

  5. leetcode刷题-50Pow(x, n)

    题目 实现 pow(x, n) ,即计算 x 的 n 次幂函数. 思路 最初的想法n>0计算res = res*x 计算n次,n<0,将x取倒数后同理,但结果表明计算速度太慢了. 后续应该 ...

  6. SpringBoot搭建环境

    选择文件新建一个项目 选择:Spring Initializr,其他配置不变,点击下一步 这里一般写包名和项目名,这里我就默认,直接点击下一步 这里选择:Web  --> Spring Web ...

  7. 2020重新出发,JAVA高级,JVM

    JVM的基本概念 JVM是可运行java代码的假想计算机,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收,堆和一个存储方法域.JVM是运行在操作系统之上的,它与硬件没有直接的交互. [外链图片 ...

  8. spring5源码 -- IOC容器设计理念和核心注解的作用

    一. spring源码整体脉络介绍及源码编译 二. Spring IOC的源码深入学习 2.1 ioc容器的加载过程(重要) 2.2 bean的生命周期源码深度剖析 2.3 循环依赖总结讲解 2.4 ...

  9. Java基础之LinkedHashMap原理分析

    知识准备HashMap 我们平时用LinkedHashMap的时候,都会写下面这段 LinkedHashMap<String, Object> map = new LinkedHashMa ...

  10. CEO的行为风格会影响公司业绩吗?

    中国的两大互联网巨头--腾讯和阿里,创始人的风格非常不同.在公众面前,马云的形象是高谈阔论,而马化腾则显得较为低调.在公司管理上,马云不插手具体事务,而是站在高处务虚,抓战略.抓文化,而马化腾则是腾讯 ...