用JS连接nebula-http-gateway执行命令

  • nebula 版本:v2.5.0
  • 部署方式(分布式 / 单机 / Docker / DBaaS):Docker
  • 是否为线上版本:N
  • 问题的具体描述

我用JavaScript的fetch连接上了Nebula的Http接口,但是我看到说明里面用curl访问的话会返回一个nsid:

现在想问一下JavaScript的fetch该怎么获取这个nsid?然后再问一下后面该怎么把这个nsid传过去api/db/exec来执行GSQL指令?

正常已在 gateway 的 beego 框架中将 nsid 存到 session和 cookie 中了,不用你再特殊传过去

意思是只要直接再POST到api/db/exec就可以了吗?

我直接再fetch到api/db/exec好像会报错:

var data = {
            'username':'root', 
            'password':'password', 
            'address':'10.176.161.237',
            // 'address':'10.201.47.89', 
            'port':9669
        };

    const url = "http://10.176.161.237/api/db/connect";
    // const url = "http://10.201.47.89/api/db/connect";
    
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: JSON.stringify(data) // body data type must match "Content-Type" header
    })
    .then(response => response.json())
    .then(res_data => {
      console.log(res_data);

      const url2 = "http://10.176.161.237/api/db/exec"
      var query = {
        "gql": "show spaces;"
      };

      fetch(url2, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(query)
      })
      .then(response => response.json())
      .then(d => console.log(d))
      .catch(e => console.log(e));
    })
    .catch(error => console.log(error));

请求得带上cookie信息,调用connect接口后,有关当前登录态的会话会通过http的set-cookie头字段种在cookie里面,所以你调用后面的执行语句时,检查下请求是否携带了cookie信息

在fetch里面带cookie的话是用credentials: "include"吗?

然后因为我使用nginx来作反向代理的,用了credentials: "include的话会报错,不知道该怎么调整?

    // const connect = "http://10.201.47.89/api/db/connect";

    const execute = "http://10.176.161.237/api/db/exec"
    var query = {
      "gql": "show spaces;"
    };

    const disconnect = "http://10.176.161.237/api/db/disconnect";
    
    fetch(connect, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: JSON.stringify(data) // body data type must match "Content-Type" header
    })
    .then(response => response.json())
    .then(res_data => {
      console.log(res_data);
      console.log(res_data.cookie);

      // Execute GQL
      fetch(execute, {
        method: 'POST',
        credentials: 'include',
        headers: {
          // 'Content-Type': 'application/json'
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: JSON.stringify(query)
      })
      .then(response => response.json())
      .then(d => {
        console.log(d);
        fetch_disconnect();
      })
        .catch(error => {
        console.log(error);
        fetch_disconnect();
      });
    })
    .catch(error => {
      console.log(error);
      fetch_disconnect();
    });```

image
登陆接口会有一个 set-cookie操作,你如果不是一个完整的项目的话,每次请求都需要在 headers 里面加上这个 cookie

喔是每次都要在headers里面加上这个"nsid": "nsid值"吗?这个nsid该怎么在fetch的response里面获取?还是只能用curl来登陆然后复制粘贴到headers的nsid值?

headers: {
‘cookie’: nsid=xxxx
}
你可以判断在登陆接口获取到后,给项目的接口请求做一层封装,然后在请求前做一个拦截,直接在所有接口 header 上加上就行了

没太懂 ,在fetch .then(response => …)的response是没办法直接获取到返回的那个set-cookie的吗?我试着用curl登陆然后复制到JS的fetch里面,好像没有用

fetch(execute, {
        method: 'POST',
        // credentials: 'include',
        headers: {
          'Content-Type': 'application/json',
          // 'Content-Type': 'application/x-www-form-urlencoded',
          'cookie': 'nsid=74f384206a466b8d11447b24f1358b0a'
        },
        body: JSON.stringify(query)
      })
      .then(response => response.json())
      .then(d => {
        console.log(d);
        fetch_disconnect();
      })
        .catch(error => {
        console.log(error);
        fetch_disconnect();
      });
    })
    .catch(error => {
      console.log(error);
      fetch_disconnect();
    });

这个set-cookie是放到http协议头里面的里面的,并且为了安全性,服务端设置了httponly,脚本是无法读取的,参考:

  1. 执行connect时,reponse的http头字段里通过设置set-cookie,把服务端的连接会话id种在浏览器端:

2)连接成功后,在会话有效期内,执行exec语句,通过http携带的cookie信息,服务能解析到会话id,解密找到对应的连接,执行语句:

会话id种在浏览器里了意思是说并不需要特地给HTTP传cookie吗,JS打开的浏览器是不是和Studio的不太一样?你们有没有用JS连接HTTP-Gateway和执行GQL的例子呀?我想参考一下 :grimacing:卡在这上面好久了

Studio的前端也是通过http携带cookie信息,连接到gateway的。所以不清楚你说的区别在哪里,你是自己又开发一个web前端应用么?

我现在是在试直接用JavaScript怎么样用Nebula Graph的HTTP,现在JavaScript的代码都是写在HTML文件里面的,然后我试代码都是打开html网页来看console里的结果

要是有这样的JavaScript的例子就更好了,我不太清楚这两个fetch connect和fetch exec是怎么写

另外你想看例子的话,可以看我们的开源仓库代码,相关部分:

按你这个js代码,你connect能执行成功对吧?但是接着执行exec的时候有报错?

嗯对,现在fetch connect 和fetch exec的代码是这个样子

fetch(connect, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: JSON.stringify(data) // body data type must match "Content-Type" header
    })
    .then(response => response.json())
    .then(res_data => {
      console.log(res_data);

      // Execute GQL
      fetch(execute, {
        method: 'POST',
        // credentials: 'include',
        headers: {
          'Content-Type': 'application/json',
          // 'Content-Type': 'application/x-www-form-urlencoded',
          // 'cookie': 'nsid=74f384206a466b8d11447b24f1358b0a'
        },
        body: JSON.stringify(query)
      })
      .then(response => response.json())
      .then(d => {
        console.log(d);
        fetch_disconnect();
      })
        .catch(error => {
        console.log(error);
        fetch_disconnect();
      });
    })
    .catch(error => {
      console.log(error);
      fetch_disconnect();
    });

然后结果:

就是exec每次都是返回’connection refused for lack of session’

看起来没有传递connect建立连接后的nsid,这个是包含在cookie里,通过http的头字段传过去的,你再检查下?

或者有个建议,你可以把studio拷贝下来,在里面修改你的代码来进行尝试?

1 个赞

OK,搞定了,貌似是我用nginx作反向代理的问题,没有发cookie回去

1 个赞