从一个GraphQL API转发多部分请求到另一个GraphQL API

从一个GraphQL API转发多部分请求到另一个GraphQL API

问题描述:

我正在通过多部分请求从浏览器上载文件到由graphql-yoga提供支持的GraphQL-API,后者由express提供支持.现在,我要将这个完全相同的请求正文转发到另一个GraphQL-API.

I'm uploading files from the browser via a multipart request to a GraphQL-API which is powered by graphql-yoga which is powered by express. Now I want to forward this exact same request body to another GraphQL-API.

const fetch = require('node-fetch');

async passThrough(args, opts) {
  const { body, getRawBody, headers, method } = opts.request;
  var rawBody;
  if (body.files && body.files.length) {
    rawBody = await getRawBody;
  } else {
    rawBody = typeof body == 'string' ? body : JSON.stringify(body)
  }
  let options = {
    body: rawBody,
    method, headers
  };
  var res = await fetch(otherApiUrl, options).then((res) => {
    return res.json();
  });
  return res;
}

在此函数中,我将身体作为对象.但它包括文件"作为我无法简单转发的承诺(无法找到任何办法做到这一点).因此,我尝试通过快速的中间件获取原始内容,并使用 await getRawBody 像上面一样访问它.

In this function I get the body as an object. But it includes "files" as promises which I can't simply forward (Couldn't find anything to do it). So I tried to get the raw body through a express middleware and access it like above with await getRawBody.

function getRawBody(req, res, next) {
  req.getRawBody = new Promise(resolve => {
    var buf = '';
    req.on('data', x => buf += x);
    req.on('end', () => {
      resolve(buf);
    });
  });
  next();
}

server.express.use(getRawBody);

它将请求传递给另一个API,但是文件不再是有效的jpeg.我发现,上传的文件与原始文件相比有些偏移.我可能做错了什么?

It passes the request to the other API but the files are no valid jpegs anymore. I found out, that the uploaded file is shifted some bits from the original file. What am I maybe doing wrong?

我在在此处找到了解决方案,并对功能进行了修改得到原始的身体.现在,文件内容不再在目标主机上移动.

I found a solution here and adapted the function to get the raw body. Now the file contents are not shifted anymore on the target host.

const concatStream = require('concat-stream');
function getRawBody(req, res, next) {
  req.getRawBody = new Promise(resolve => {
    req.pipe(concatStream(function (data) {
      resolve(data);
    }));
  });
  next();
}