Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2019-08-06 20:54:53 +08:00
commit 8dabf65213
3 changed files with 203 additions and 222 deletions

View File

@ -1,3 +1,4 @@
0x996 is translating
IT disaster recovery: Sysadmins vs. natural disasters | HPE
======

View File

@ -1,222 +0,0 @@
How to test Webhooks when youre developing locally
============================================================
![](https://cdn-images-1.medium.com/max/1000/1*0HNQmPw5yXva6powvVwn5Q.jpeg)
Photo by [Fernando Venzano][1] on [Unsplash][2]
[Webhooks][10] can be used by an external system for notifying your system about a certain event or update. Probably the most well known type is the one where a Payment Service Provider (PSP) informs your system about status updates of payments.
Often they come in the form where you listen on a predefined URL. For example [http://example.com/webhooks/payment-update][11]. Meanwhile the other system sends a POST request with a certain payload to that URL (for example a payment ID). As soon as the request comes in, you fetch the payment ID, ask the PSP for the latest status via their API, and update your database afterward.
Other examples can be found in this excellent explanation about Webhooks. [https://sendgrid.com/blog/whats-webhook/][12].
Testing these webhooks goes fairly smoothly as long as the system is publicly accessible over the internet. This might be your production environment or a publicly accessible staging environment. It becomes harder when you are developing locally on your laptop or inside a Virtual Machine (VM, for example, a Vagrant box). In those cases, the local URLs are not publicly accessible by the party sending the webhook. Also, monitoring the requests being sent around is be difficult, which might make development and debugging hard.
What will this example solve:
* Testing webhooks from a local development environment, which is not accessible over the internet. It cannot be accessed by the service sending the data to the webhook from their servers.
* Monitor the requests and data being sent around, but also the response your application generates. This will allow easier debugging, and therefore a shorter development cycle.
Prerequisites:
* _Optional_ : in case you are developing using a Virtual Machine (VM), make sure its running and make sure the next steps are done in the VM.
* For this tutorial, we assume you have a vhost defined at `webhook.example.vagrant`. I used a Vagrant VM for this tutorial, but you are free in choosing the name of your vhost.
* Install `ngrok`by following the [installation instructions][3]. Inside a VM, I find the Node version of it also useful: [https://www.npmjs.com/package/ngrok][4], but feel free to use other methods.
I assume you dont have SSL running in your environment, but if you do, feel free to replace port 80 with port 433 and  `_http://_`  with  `_https://_`  in the examples below.
#### Make the webhook testable
Lets assume the following example code. Ill be using PHP, but read it as pseudo-code as I left some crucial parts out (for example API keys, input validation, etc.)
The first file:  _payment.php_ . This file creates a payment object and then registers it with the PSP. It then fetches the URL the customer needs to visit in order to pay and redirects the user to the customer in there.
Note that the `webhook.example.vagrant` in this example is the local vhost weve defined for our development set-up. Its not accessible from the outside world.
```
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
'webhook_url' => 'http://webhook.example.vagrant/webhook.php',
];
```
```
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
```
Second file:  _webhook.php_ . This file waits to be called by the PSP to get notified about updates.
```
<?php
/*
* This file gets called by the PSP and in the $_POST they submit an 'id'
* We can use this ID to get the latest status from the PSP and update our internal systems afterward
*/
```
```
$paymentId = $_POST['id'];
$paymentInfo = $paymentProvider->getPayment($paymentId);
$status = $paymentInfo->getStatus();
```
```
// Perform actions in here to update your system
if ($status === 'paid') {
..
}
elseif ($status === 'cancelled') {
..
}
```
Our webhook URL is not accessible over the internet (remember: `webhook.example.vagrant`). Thus, the file  _webhook.php_  will never be called by the PSP. Your system will never get to know about the payment status. This ultimately leads to orders never being shipped to customers.
Luckily,  _ngrok_  can in solving this problem.  [_ngrok_][13]  describes itself as:
> ngrok exposes local servers behind NATs and firewalls to the public internet over secure tunnels.
Lets start a basic tunnel for our project. On your environment (either on your system or on the VM) run the following command:
`ngrok http -host-header=rewrite webhook.example.vagrant:80`
Read about more configuration options in their documentation: [https://ngrok.com/docs][14].
A screen like this will come up:
![](https://cdn-images-1.medium.com/max/1000/1*BZZE-CvZwHZ3pxsElJMWbA.png)
ngrok output
What did we just start? Basically, we instructed `ngrok` to start a tunnel to `[http://webhook.example.vagr][5]ant` at port 80\. This same URL can now be reached via `[http://39741ffc.ngrok.i][6]o` or `[https://39741ffc.ngrok.io][7]`[,][15] They are publicly accessible over the internet by anyone that knows this URL.
Note that you get both HTTP and HTTPS available out of the box. The documentation gives examples of how to restrict this to HTTPS only: [https://ngrok.com/docs#bind-tls][16].
So, how do we make our webhook work now? Update  _payment.php_  to the following code:
```
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
'webhook_url' => 'https://39741ffc.ngrok.io/webhook.php',
];
```
```
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
```
Now, we told the PSP to call the tunnel URL over HTTPS.  _ngrok_  will make sure your internal URL gets called with an unmodified payload, as soon as the PSP calls the webhook via the tunnel.
#### How to monitor calls to the webhook?
The screenshot youve seen above gives an overview of the calls being made to the tunnel host. This data is rather limited. Fortunately, `ngrok` offers a very nice dashboard, which allows you to inspect all calls:
![](https://cdn-images-1.medium.com/max/1000/1*qZw9GRTnG1sMgEUmsJPz3g.png)
I wont go into this very deep because its self-explanatory as soon as you have it running. Therefore I will explain how to access it on the Vagrant box as it doesnt work out of the box.
The dashboard will allow you to see all the calls, their status codes, the headers and data being sent around. You will also see the response your application generated.
Another neat feature of the dashboard is that it allows you to replay a certain call. Lets say your webhook code ran into a fatal error, it would be tedious to start a new payment and wait for the webhook to be called. Replaying the previous call makes your development process way faster.
The dashboard by default is accessible at [http://localhost:4040.][17]
#### Dashboard in a VM
In order to make this work inside a VM, you have to perform some additional steps:
First, make sure the VM can be accessed on port 4040\. Then, create a file inside the VM holding this configuration:
`web_addr: 0.0.0.0:4040`
Now, kill the `ngrok` process thats still running and start it with this slightly adjusted command:
`ngrok http -config=/path/to/config/ngrok.conf -host-header=rewrite webhook.example.vagrant:80`
You will get a screen looking similar to the previous screenshot though the IDs have changed. The previous URL doesnt work anymore, but you got a new URL. Also, the `Web Interface` URL got changed:
![](https://cdn-images-1.medium.com/max/1000/1*3FZq37TF4dmBqRc1R0FMVg.png)
Now direct your browser to `[http://webhook.example.vagrant:4040][8]` to access the dashboard. Also, make a call to `[https://e65642b5.ngrok.io/webhook.php][9]`[.][18]This will probably result in an error in your browser, but the dashboard should show the request being made.
#### Final remarks
The examples above are pseudo-code. The reason is that every external system uses webhooks in a different way. I tried to give an example based on a fictive PSP implementation, as probably many developers have to deal with payments at some moment.
Please be aware that your webhook URL can also be used by others with bad intentions. Make sure to validate any input being sent to it.
Preferably also add a token to the URL which is unique for each payment. This token must only be known by your system and the system sending the webhook.
Good luck testing and debugging your webhooks!
Note: I havent tested this tutorial on Docker. However, this Docker container looks like a good starting point and includes clear instructions. [https://github.com/wernight/docker-ngrok][19].
Stefan Doorn
[https://github.com/stefandoorn][20]
[https://twitter.com/stefan_doorn][21]
[https://www.linkedin.com/in/stefandoorn][22]
--------------------------------------------------------------------------------
作者简介:
Backend Developer (PHP/Node/Laravel/Symfony/Sylius)
--------
via: https://medium.freecodecamp.org/testing-webhooks-while-using-vagrant-for-development-98b5f3bedb1d
作者:[Stefan Doorn ][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://medium.freecodecamp.org/@stefandoorn
[1]:https://unsplash.com/photos/MYTyXb7fgG0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[2]:https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[3]:https://ngrok.com/download
[4]:https://www.npmjs.com/package/ngrok
[5]:http://webhook.example.vagrnat/
[6]:http://39741ffc.ngrok.io/
[7]:http://39741ffc.ngrok.io/
[8]:http://webhook.example.vagrant:4040/
[9]:https://e65642b5.ngrok.io/webhook.php.
[10]:https://sendgrid.com/blog/whats-webhook/
[11]:http://example.com/webhooks/payment-update%29
[12]:https://sendgrid.com/blog/whats-webhook/
[13]:https://ngrok.com/
[14]:https://ngrok.com/docs
[15]:http://39741ffc.ngrok.io%2C/
[16]:https://ngrok.com/docs#bind-tls
[17]:http://localhost:4040./
[18]:https://e65642b5.ngrok.io/webhook.php.
[19]:https://github.com/wernight/docker-ngrok
[20]:https://github.com/stefandoorn
[21]:https://twitter.com/stefan_doorn
[22]:https://www.linkedin.com/in/stefandoorn

View File

@ -0,0 +1,202 @@
当你在本地开发时如何测试 Webhooks
===================
![](https://cdn-images-1.medium.com/max/1000/1*0HNQmPw5yXva6powvVwn5Q.jpeg)
[Webhooks][10] 可用于外部系统通知你的系统发生了某个事件或更新。可能最知名的 [Webhooks][10] 是支付服务提供商PSP通知你的系统支付状态有了更新。
它们通常以你在监听预定义 URL 的形式出现,例如 `http://example.com/webhooks/payment-update`。 同时,另一个系统向该 URL 发送具有特定有效载荷的 POST 请求(例如支付 ID。一旦请求进入你就会获取支付 ID可以通过它们的 API 用这个支付 ID 向 PSP 询问最新状态,然后更新你的数据库。
其他例子可以在这个对 Webhook 的出色的解释中找到:[https://sendgrid.com/blog/whats-webhook/][12]。
只要系统可通过互联网公开访问(这可能是你的生产环境或可公开访问的临时环境),测试这些 webhook 就相当顺利。而当你在笔记本电脑上或虚拟机内部进行本地开发例如Vagrant 虚拟机)时,它变得困难了。在这些情况下,发送 webhook 的一方无法公开访问本地 URL。此外监视发送的请求也很困难这可能使开发和调试变得困难。
因此,这个例子将解决:
* 测试来自本地开发环境的 webhook该环境无法通过互联网访问。从服务器向 webhook 发送数据的服务无法访问它。
* 监控发送的请求和数据,以及应用程序生成的响应。这样可以更轻松地进行调试,从而缩短开发周期。
前置需求:
* *可选*如果你使用虚拟机VM进行开发请确保它正在运行并确保在 VM 中完成后续步骤。
* 对于本教程,我们假设你定义了一个 vhost`webhook.example.vagrant`。我在本教程中使用了 Vagrant VM但你可以自由选择 vhost 的名称。
* 按照[安装说明][3]安装 `ngrok`。 在 VM 中,我发现它的 Node 版本也很有用:[https://www.npmjs.com/package/ngrok][4],但你可以随意使用其他方法。
我假设你没有在你的环境中运行 SSL但如果你这样做了请将在下面的示例中的端口 80 替换为端口 433`http://` 替换为 `https://`
### 使 webhook 可测试
我们假设以下示例代码。我将使用 PHP但将其视作伪代码因为我留下了一些关键部分例如 API 密钥、输入验证等)没有编写。
第一个文件:`payment.php`。此文件创建一个 `$payment` 对象,将其注册到 PSP。然后它获取客户需要访问的 URL以便支付并将用户重定向到客户那里。
请注意,此示例中的 `webhook.example.vagrant` 是我们为开发设置定义的本地虚拟主机。它无法从外部世界进入。
```
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
'webhook_url' => 'http://webhook.example.vagrant/webhook.php',
];
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
```
第二个文件:`webhook.php`。此文件等待 PSP 调用以获得有关更新的通知。
```
<?php
/*
* This file gets called by the PSP and in the $_POST they submit an 'id'
* We can use this ID to get the latest status from the PSP and update our internal systems afterward
*/
$paymentId = $_POST['id'];
$paymentInfo = $paymentProvider->getPayment($paymentId);
$status = $paymentInfo->getStatus();
// Perform actions in here to update your system
if ($status === 'paid') {
..
}
elseif ($status === 'cancelled') {
..
}
```
我们的 webhook URL 无法通过互联网访问(请记住它:`webhook.example.vagrant`。因此PSP 永远不可能调用文件 `webhook.php`。 你的系统将永远不会知道付款状态。这最终导致订单永远不会被运送给客户。
幸运的是,`ngrok` 可以解决这个问题。 [ngrok][13] 将自己描述为:
> ngrok 通过安全隧道将 NAT 和防火墙后面的本地服务器暴露给公共互联网。
让我们为我们的项目启动一个基本的隧道。在你的环境中(在你的系统上或在 VM 上)运行以下命令:
```
ngrok http -host-header=rewrite webhook.example.vagrant:80
```
> 阅读其文档可以了解更多配置选项:[https://ngrok.com/docs][14]。
会出现这样的屏幕:
![](https://cdn-images-1.medium.com/max/1000/1*BZZE-CvZwHZ3pxsElJMWbA.png)
*ngrok 输出*
我们刚刚做了什么?基本上,我们指示 `ngrok` 在端口 80 建立了一个到 `http://webhook.example.vagrant` 的隧道。同一个 URL 也可以通过 `http://39741ffc.ngrok.io``https://39741ffc.ngrok.io` 访问。它们能被任何知道此 URL 的人通过互联网公开访问。
请注意,你可以同时获得 HTTP 和 HTTPS 两个服务。该文档提供了如何仅将此限制为 HTTPS 的示例:[https://ngrok.com/docs#bind-tls][16]。
那么,我们如何让我们的 webhook 现在工作起来?将 `payment.php` 更新为以下代码:
```
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
'webhook_url' => 'https://39741ffc.ngrok.io/webhook.php',
];
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
```
现在,我们告诉 PSP 通过 HTTPS 调用此隧道 URL。只要 PSP 通过隧道调用 webhook`ngrok` 将确保使用未修改的有效负载调用内部 URL。
### 如何监控对 webhook 的调用?
你在上面看到的屏幕截图概述了对隧道主机的调用。这些数据相当有限。幸运的是,`ngrok` 提供了一个非常好的仪表板,允许你检查所有调用:
![](https://cdn-images-1.medium.com/max/1000/1*qZw9GRTnG1sMgEUmsJPz3g.png)
我不会深入研究这个问题,因为它是不言自明的,你只要运行它就行了。因此,我将解释如何在 Vagrant 虚拟机上访问它,因为它不是开箱即用的。
仪表板将允许你查看所有调用、其状态代码、标头和发送的数据。你将看到应用程序生成的响应。
仪表板的另一个优点是它允许你重放某个调用。假设你的 webhook 代码遇到了致命的错误,开始新的付款并等待 webhook 被调用将会很繁琐。重放上一个调用可以使你的开发过程更快。
默认情况下,仪表板可在 `http://localhost:4040` 访问。
### 虚拟机中的仪表盘
为了在 VM 中完成此工作,你必须执行一些额外的步骤:
首先,确保可以在端口 4040 上访问 VM。然后在 VM 内创建一个文件已存放此配置:
```
web_addr: 0.0.0.0:4040
```
现在,杀死仍在运行的 `ngrok` 进程,并使用稍微调整过的命令启动它:
```
ngrok http -config=/path/to/config/ngrok.conf -host-header=rewrite webhook.example.vagrant:80
```
尽管 ID 已经更改,但你将看到类似于上一屏幕截图的屏幕。之前的网址不再有效,但你有了一个新网址。 此外,`Web Interface` URL 已更改:
![](https://cdn-images-1.medium.com/max/1000/1*3FZq37TF4dmBqRc1R0FMVg.png)
现在将浏览器指向 `http://webhook.example.vagrant:4040` 以访问仪表板。另外,对 `https://e65642b5.ngrok.io/webhook.php` 做个调用。这可能会导致你的浏览器出错,但仪表板应显示正有一个请求。
#### 最后的评论
上面的例子是伪代码。原因是每个外部系统都以不同的方式使用 webhook。我试图基于一个虚构的 PSP 实现给出一个例子,因为可能很多开发人员在某个时刻肯定会处理付款。
请注意,你的 webhook 网址也可能被意图不好的其他人使用。确保验证发送给它的任何输入。
更好的的,可以向 URL 添加令牌,该令牌对于每个支付是唯一的。只有你的系统和发送 webhook 的系统才能知道此令牌。
祝你测试和调试你的 webhook 顺利!
注意:我没有在 Docker 上测试过本教程。但是,这个 Docker 容器看起来是一个很好的起点,并包含了明确的说明:[https://github.com/wernight/docker-ngrok][19] 。
--------
via: https://medium.freecodecamp.org/testing-webhooks-while-using-vagrant-for-development-98b5f3bedb1d
作者:[Stefan Doorn][a]
译者:[wxy](https://github.com/wxy)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://medium.freecodecamp.org/@stefandoorn
[1]:https://unsplash.com/photos/MYTyXb7fgG0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[2]:https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[3]:https://ngrok.com/download
[4]:https://www.npmjs.com/package/ngrok
[5]:http://webhook.example.vagrnat/
[6]:http://39741ffc.ngrok.io/
[7]:http://39741ffc.ngrok.io/
[8]:http://webhook.example.vagrant:4040/
[9]:https://e65642b5.ngrok.io/webhook.php.
[10]:https://sendgrid.com/blog/whats-webhook/
[11]:http://example.com/webhooks/payment-update%29
[12]:https://sendgrid.com/blog/whats-webhook/
[13]:https://ngrok.com/
[14]:https://ngrok.com/docs
[15]:http://39741ffc.ngrok.io%2C/
[16]:https://ngrok.com/docs#bind-tls
[17]:http://localhost:4040./
[18]:https://e65642b5.ngrok.io/webhook.php.
[19]:https://github.com/wernight/docker-ngrok
[20]:https://github.com/stefandoorn
[21]:https://twitter.com/stefan_doorn
[22]:https://www.linkedin.com/in/stefandoorn