如何在 Postman 中可视化 API 混搭? [英] How can I visualize an API mashup in Postman?

查看:106
本文介绍了如何在 Postman 中可视化 API 混搭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个经典演员的 REST API,我想在 Postman 中对其进行可视化.演员的图片 URL 不在 API 中,因此我需要创建一个由核心 API 和其他 API 组合而成的混搭.

1.先决条件

核心 API/端点位于

4.有用吗?

那么有效吗?– 答案是肯定的和否定的.

  • 从好的方面来说,我可以创建所需的 JSON mashup 结果,如下所示以上第 2 节.
  • 不好的一面是,可视化失败了:

消息为此请求设置可视化工具是典型的对 pm.visualizer.set() 的调用已被遗忘.但我没有没有忘记它.那么有什么问题?

5.如何在 Postman 中复制我的尝试

在 Postman 中复制我的尝试应该很简单.
假设您使用的是

2.有用吗?

是的!– 它有效:

3.如何在 Postman 中复制我的解决方案

假设您使用的是桌面版 Postman,请执行以下操作:

  1. 下载并保存
    http://henke.atwebpages.com/postman/actors/Actors.pm_coll.json
    在硬盘上的合适位置.

  2. 在 Postman 中,Ctrl + O >上传文件 >Actors.pm_coll.json >导入.

  3. 集合 >演员 >DummyRequest >发送.

  4. 在 Postman Response Body 中,点击 Visualize.

  5. 完成!– 您现在应该看到如上的输出.

参考资料


1我希望 Postman 在未来的版本中支持 promise.
2 再一次,不要被这些行弄糊涂了const lock = setTimeout(() => {}, 43210);clearTimeout(lock);.——它们的唯一目的是作为 解决已知错误.

I have a REST API of classical actors that I want to visualize in Postman. The image URL of an actor is not in the API, so I will need to create a mashup from a combination of the core API and another API.

1. Prerequisites

The core API/endpoint is at http://henke.atwebpages.com/postman/actors/actors.json:

{
  "area": {
    "name": "United States",
    "type": null
  },
  "release-groups": [
    {
      "primary-type": "Actor",
      "fullname": "Katharine Hepburn",
      "id": "Q56016",
      "born": "1907"
    },
    {
      "primary-type": "Actor",
      "fullname": "Humphrey Bogart",
      "id": "Q16390",
      "born": "1899"
    }
  ],
  "country": "US",
  "name": "Classical Actors",
  "life-span": {
    "begin": "1899",
    "ended": true,
    "end": "2003"
  }
}

The image URLs of Katharine Hepburn and Humphrey Bogart are at:
http://henke.atwebpages.com/postman/actors/coverart/Q56016.json and
http://henke.atwebpages.com/postman/actors/coverart/Q16390.json, respectively.

The corresponding JSONS, Katharine Hepburn:

{
  "images": [
    {
      "front": true,
      "thumbnails": {
        "small": "https://upload.wiki [...] 220px-Tom_cruise_1989.jpg",
        "large": "https://upload.wiki [...] -TomCruiseDec08MTV_cropped.jpg"
      },
      "back": false,
      "edit": 18084161
    },
    {
      "back": true,
      "edit": 39938947,
      "front": false,
      "thumbnails": {
        "small": "https://upload.wiki [...] -Katharine_Hepburn_promo_pic.jpg",
        "large": "https://upload.wiki [...] Tom_Cruise_by_Gage_Skidmore_2.jpg"
      }
    }
  ]
}

and Humphrey Bogart:

{
  "images": [
    {
      "edit": 40403385,
      "back": true,
      "thumbnails": {
        "small": "https://upload.wiki [...] 220px-Humphrey_Bogart_1940.jpg",
        "large": "https://upload.wiki [...] px-TomCruiseByIanMorris2010.jpg"
      },
      "front": false
    },
    {
      "edit": 40403384,
      "back": false,
      "thumbnails": {
        "small": "https://upload.wiki [...] 220px-Tom_cruise_1989.jpg",
        "large": "https://upload.wiki [...] -TomCruiseDec08MTV_cropped.jpg"
      },
      "front": true
    }
  ]
}

where I have truncated the links of the images for better readability.

Note in the core API how each object/person has a unique id (Q56016 for Katharine Hepburn and Q16390 for Humphrey Bogart) and a fullname. The other endpoints have – for each object in the release-groups array of the core API – the same unique identifier, along with a link to an image/portrait. Thus, information from all three endpoints is needed to list each actor with a matching image.

2. The desired resulting mashup

Obviously, the problem is solved if the data in the APIs can be combined together in such a way that – for each identifier – both the name and the image link are supplied:

[
  {
    "name": "Katharine Hepburn",
    "image": "https://upload.wiki [...] -Katharine_Hepburn_promo_pic.jpg"
  },
  {
    "name": "Humphrey Bogart",
    "image": "https://upload.wiki [...] 220px-Humphrey_Bogart_1940.jpg"
  }
]

Then it remains to visualize the data in Postman.

3. Methodology

I will write all code in a single Tests script of a Postman request. That request is just a dummy that serves no other purpose than to start running the Tests script.

To construct the mashup and then display the result, it would be convenient to use the well-known Fetch API and then get the images by using Promise.all.

One caveat is that Postman does not implement the Fetch API.
But luckily there is an answer that explains how to mimic the fetch() command in Postman.
It can be done as follows:

function fetch (url) {
  return new Promise((resolve, reject) => {
    pm.sendRequest(url, function (_, fetchResponse) {
      resolve(fetchResponse);
    });
  });
} // ^^ No Fetch API in Postman! But see https://stackoverflow.com/a/67588692

Since this fetch() function returns a promise, it should (hopefully) work the same way as fetch() in any modern web browser.

The rest of the Tests section should construct the result. Note how Promise.all needs to be chained/nested with the first request fetch(urlOuter) – because it needs data from it.
This is analogous to the second Stack Snippet of this answer.
Finally, the result should be visualized: 1

const lock = setTimeout(() => {}, 43210);
const fullnames = [];
const urls = [];
const urlOuter = 'http://henke.atwebpages.com/postman/actors/actors.json';
fetch(urlOuter).then(responseO => responseO.json()).then(responseBodyO => {
  const tblHeader = responseBodyO.name;
  const actors = responseBodyO['release-groups'];
  for (const item of actors) {
    fullnames.push(item.fullname);
    urls.push('http://henke.atwebpages.com/postman/actors/coverart/' +
        item.id + '.json');
  }
  return Promise.all(urls.map(url => fetch(url)
    .then(responseI => responseI.json())
    .then(responseBodyI => responseBodyI.images.find(obj =>
      obj.back === true).thumbnails.small)))
    .then(imageURLs => {
      clearTimeout(lock); // Unlock the timeout.
      const actorNames = fullnames.map(value => ({ name: value }));
      const actorImages = imageURLs.map(value => ({ image: value }));
      const actorsAndImages = actorNames.map(
        (item, i) => Object.assign({}, item, actorImages[i]));
      console.log('actorsAndImages:\n' + JSON.stringify(actorsAndImages));
      const template = `<table>
        <tr><th>` + tblHeader + `</th></tr>
        {{#each responseI}}
        <tr><td>{{name}}<br><img src="{{image}}"></td></tr>
        {{/each}}
      </table>`;
      pm.visualizer.set(template, { responseI: actorsAndImages });
    });
}).catch(_ => {
  console.error('Failed to fetch - ' + urlOuter);
});

In Postman:

4. Does it work?

So does it work? – The answer is both yes and no.

  • On the good side, I could create the desired JSON mashup result as in section 2 above.
  • On the bad side, the visualization fails:

The message Set up the visualizer for this request is typical when the call to pm.visualizer.set() has been forgotten. But I did not forget it. So what is wrong?

5. How to replicate my attempt in Postman

Replicating my attempt in Postman should be straightforward.
Assuming you are using the desktop version of Postman, do as follows:

  1. Download and save
    http://henke.atwebpages.com/postman/actors/Promise.all-Actors.pm_coll.json
    in a suitable place on your hard drive.

  2. In Postman, Ctrl + O > Upload Files > Promise.all-Actors.pm_coll.json > Import.
    You should now see Promise.all-Actors among your collections in Postman.

  3. Collections > Promise.all-Actors > DummyRequest > Send.

  4. In the Postman Response Body, click Visualize.

  5. Done! – If everything worked as intended, you should now see the output as above.

References


1 Don't get confused by the lines const lock = setTimeout(() => {}, 43210); and clearTimeout(lock);. – Their only purpose is to serve as a workaround for a known bug.

解决方案

The message Set up the visualizer for this request is typical when the call to pm.visualizer.set() has been forgotten. But I did not forget it. So what is wrong?

As already touched upon, the problem is that Postman does not natively support promises. 1
What does that mean? – Well, apparently it means that a function such as pm.visualizer.set() cannot be called from within the callback of a Promise. It has to be called from within the callback of pm.sendRequest(). Note that by the construction of the fetch() function the corresponding Promise is actually outside of the pm.sendRequest() callback!

1. Achieving the desired result and visualizing it

In other words, you need to replace all occurrences of fetch() with pm.sendRequest().
You also need to implement your own version of Promise.all, since it relies upon promises, something you don't have in a native Postman script.
Fortunately, such an implementation was posted in an answer the day before yesterday.

After making those changes, here is the code for the Tests section, starting with the initializations: 2

const lock = setTimeout(() => {}, 43210);
const fullnames = [];
const urls = [];
const urlOuter = 'http://henke.atwebpages.com/postman/actors/actors.json';

The main part – slightly unconventionally formatted – to avoid vertical scrolling:

pm.sendRequest(urlOuter, (_, responseO) => {
  const tblHeader = responseO.json().name;
  const actors = responseO.json()['release-groups'];
  for (const item of actors) {
    fullnames.push(item.fullname);
    urls.push('http://henke.atwebpages.com/postman/actors/coverart/' +
        item.id + '.json'); }
  const images = [];
  let countDown = urls.length;
  urls.forEach((url, index) => {
    asynchronousCall(url, imageURL => {
      images[index] = imageURL;
      if (--countDown === 0) { // Callback for ALL starts on next line.
        clearTimeout(lock); // Unlock the timeout.
        const actorNames = fullnames.map(value => ({ name: value }));
        const actorImages = images.map(value => ({ image: value }));
        const actorsAndImages = actorNames.map(
          (item, i) => Object.assign({}, item, actorImages[i]));
        console.log('actorsAndImages:\n' + JSON.stringify(actorsAndImages));
        const template = `<table>
          <tr><th>` + tblHeader + `</th></tr>
          {{#each responseI}}
          <tr><td>{{name}}<br><img src="{{image}}"></td></tr>
          {{/each}}
        </table>`;
        pm.visualizer.set(template, { responseI: actorsAndImages });
      }
    });
  });
  function asynchronousCall (url, callback) {
    pm.sendRequest(url, (_, responseI) => {
      callback(responseI.json().images.find(obj => obj.back === true)
        .thumbnails.small); // Individual callback.
    }); } });

In Postman:

2. Does it work?

Yes! – It works:

3. How to replicate my solution in Postman

Assuming you are using the desktop version of Postman, do as follows:

  1. Download and save
    http://henke.atwebpages.com/postman/actors/Actors.pm_coll.json
    in a suitable place on your hard drive.

  2. In Postman, Ctrl + O > Upload Files > Actors.pm_coll.json > Import.

  3. Collections > Actors > DummyRequest > Send.

  4. In the Postman Response Body, click Visualize.

  5. Done! – You should now see the output as above.

References


1 I hope Postman will support promises in a future version.
2 Again, don't get confused by the lines const lock = setTimeout(() => {}, 43210); and clearTimeout(lock);. – Their only purpose is to serve as a workaround for a known bug.

这篇关于如何在 Postman 中可视化 API 混搭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆