hasura的golang反向代理
概述
一直在寻找一个好用的 graphql 服务, 之前使用比较多的是 prisma, 但是 prisma1 很久不再维护了, 而 prisma2 仅仅就是一个 ORM, 不是一个完备的系统.
后来, 朋友介绍了一个 graphql 引擎 hasura, 这个是完备的系统,
不仅提供 UI 来创建数据库和表结构. 还有相应的权限控制, 也有对接第三方服务的 Events, 对数据更多控制的 Actions.
为了使用其 graphql 接口, 同样, 和之前使用 prisma 时一样, 用 golang 的 gin 框架作为 gateway, 对 graphql 接口做一层反向代理.
数据的操作基本都使用 hasura 的 graphql 接口, 逻辑比较复杂的, 或者是文件 上传/下载 相关的, 利用 gin 开发 restful 接口.
反向代理代码
对请求的处理
路由部分
1 r := gin.Default()
2 apiV1 := r.Group("/api/v1")
3
4 // proxy hasura graphql
5 authRoute.POST("/graphql", ReverseProxy())
处理请求的 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反向代理的更多相关文章
- golang 反向代理
服务器 package main import ( "bytes" "encoding/base64" "encoding/json" &q ...
- golang 实现HTTP代理和反向代理
正向代理 package main import ( "fmt" "io" "net" "net/http" " ...
- golang http proxy反向代理
本文介绍golang中如何进行反向代理. 下面例子中, proxy server接收client 的 http request,转发给true server,并把 true server的返回结果再发 ...
- golang学习笔记9 beego nginx 部署 nginx 反向代理 golang web
golang学习笔记9 beego nginx 部署 nginx 反向代理 golang web Nginx 部署 - beego: 简约 & 强大并存的 Go 应用框架https://bee ...
- IIS 反向代理 golang web开发
一. beego 开发编译 bee run 后会编译成 exe文件 编译生成后发布文件结构为 cmd 运行 cd D:/run beegoDemo.exe run 默认配置端口 不能为 80 跟iis ...
- aProxy: 带认证授权和权限控制的反向代理
前段时间很多数据库因为没有做好权限控制暴露在外网被删然后遭勒索的事件,而类似的有些内网的web服务也会被开放到公网并且没有做任何权限控制的,这样也会有一定的风险.所以就决定写篇文章简单介绍一个小工具. ...
- Nginx插件之openresty反向代理和日志滚动配置案例
Nginx插件之openresty反向代理和日志滚动配置案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.openresty介绍 1>.Nginx介绍 Nginx是一款 ...
- prisma反向代理
概要 为什么要做 prisma 的反向代理 反向代理示例(by golang) prisma 服务 gateway 服务 整体流程 认证 反向代理 权限 总结 概要 接触 prisma 有段时间了, ...
- Nginx-正反向代理及负载均衡
目录 正/反向代理 代理的方式 Nginx代理服务支持的协议 代理实战 部署web01 部署Lb01 Nginx代理常用参数 添加发往后端服务器的请求头信息 代理到后端的TCP连接.响应.返回等超时时 ...
随机推荐
- Jmeter-添加用户变量
1. 创建用户定义的变量. 2. 3. 4.输出结果:
- 计算Pi
程序: package pai; import java.math.BigDecimal; public class ComplexPi { BigDecimal result; public Com ...
- jzoj 3567. 【GDKOI2014】石油储备计划
Problem Description Input Output 对于每组数据,输出一个整数,表示达到"平衡"状态所需的最小代价. Data Constraint 对于20%的数据 ...
- python列表,字典,元组常用方法和集合
python 目录 一.列表 列表格式 1.添加 列表取数(按照下标取,下标从0开始) 获取长度 append添加(直接添加) extend添加(分别添加) insert()insert(index, ...
- golang 条件语句 for range 分析
for range 作为 golang中的语法糖提供了便利操作; 对于for range 支持 的数据类型包含: 数组以及指向数组的指针 切片 字典 通道 字符串 在range的语法糖中提供了一下特殊 ...
- domReady的理解
domReady的理解 domReady是名为DOMContentLoaded事件的别称,当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表.图 ...
- Powershell编程基础-001-基本语法
变量的定义:$a="abc" 变量的引用也是echo $a 注释: 1.单行注释:单行注释是在每行的开头键入井号#的注释. #符号右边的所有内容都将被忽略,也可以在 ...
- Shell学习(四)Shell运算符
一.基础运算 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. #计算两个数 ...
- .net core中的那些常用的日志框架(Logging篇)
前言 日志,在我们每个项目中是必不可少的,它不仅能在调试的时候测试数据,而且在项目上线,也是我们排查错误的得力助手,那我就能谈谈,用的多的几个日志框架吧!如果有不对的地方,欢迎来指教错误,谢谢! As ...
- 微服务实战系列(七)-网关springcloud gateway
1. 场景描述 springcloud刚推出的时候用的是netflix全家桶,路由用的zuul,但是据说zull1.0在大数据量访问的时候存在较大性能问题,2.0就没集成到springcloud中了, ...