graphql和rest
API gateways are great for development teams because they expose the data you need for all kinds of different purposes in a central location. There are a few great REST API gateways out there, like KrakenD, but what if you wanted to go in a different direction and choose GraphQL for your API infrastructure? Well, that works out perfectly, as it’s one of the goals of GraphQL: Abstracting many different services into a single place and allowing the developers very fine-grained control over the data they need.
API网关非常适合开发团队使用,因为它们可以在中央位置公开您需要用于各种不同目的的数据。 那里有一些很棒的REST API网关,例如KrakenD ,但是如果您想朝另一个方向去选择GraphQL作为您的API基础结构怎么办? 好吧,这很完美,因为它是GraphQL的目标之一:将许多不同的服务抽象到一个地方,并允许开发人员对所需数据进行非常细粒度的控制。
In this post, we’re going to look over a GraphQL implementation, which keeps the previous sentence in mind: Abstracting existing REST API Endpoints into a fast GraphQL server. To build the GraphQL server, we’re going to use Golang: It’s fast, it’s memory efficient, and provides just enough tools, but not too many. The GraphQL package we’ll use is github.com/graphql-go/graphql. This package is very closely aligned with the JavaScript implementation graphql-js. This makes it a perfect candidate because you’ll be able to follow JavaScript tutorials and be able to port this to Go.
在本文中,我们将研究一个GraphQL实现,该实现牢记了前面的句子:将现有的REST API端点抽象到快速的GraphQL服务器中。 为了构建GraphQL服务器,我们将使用Golang:它速度快,内存效率高,并且只提供了足够的工具,但数量不多。 我们将使用的GraphQL软件包是github.com/graphql-go/graphql 。 该软件包与JavaScript实现graphql-js紧密结合。 这使它成为理想的候选人,因为您将能够遵循JavaScript教程并将其移植到Go。
入口点 (The entry point)
To show how you can abstract an existing REST API Endpoint in GraphQL, we’re going to need an example project. I’ve created an example project at github.com/roelofjan-elsinga/graphql-rest-abstraction. You can use this to follow along in this post, as I will go over different parts of the GraphQL server and explain what’s going on.
为了展示如何在GraphQL中抽象现有的REST API端点,我们将需要一个示例项目。 我已经在github.com/roelofjan-elsinga/graphql-rest-abstraction创建了一个示例项目。 您可以使用它来完成本文,因为我将遍历GraphQL服务器的不同部分并说明发生了什么。
The entry point of our GraphQL server is main.go. Here we specify two resources in our GraphQL server: users and user.
我们的GraphQL服务器的入口点是main.go。 在这里,我们在GraphQL服务器中指定两个资源:用户和用户。
We intend to use a dummy REST API service to fetch JSON data for all users and also a single user. The “users” resources will be used to fetch all users at https://jsonplaceholder.typicode.com/users, while the “user” resource will be used to fetch a single user by ID from https://jsonplaceholder.typicode.com/users/1 or any other user available to us.
我们打算使用虚拟REST API服务来为所有用户以及单个用户获取JSON数据。 “用户”资源将用于通过https://jsonplaceholder.typicode.com/users获取所有用户,而“用户”资源将用于通过ID从https://jsonplaceholder.typicode获取单个用户。 com / users / 1或我们可用的任何其他用户。
获取所有用户 (Fetching all users)
Now that we have a REST API we can use, we can create a resource to be able to fetch this data through a GraphQL resource. You can find this resource in queries/users.go:
现在我们有了可以使用的REST API,我们可以创建资源以能够通过GraphQL资源获取此数据。 您可以在query / users.go中找到此资源:
Here you’ll find a method “fetchUsers”, where we call the REST API endpoint and convert the data into a Go struct, which is located in models/user.go. Our field “Users”, will return the User slice from “fetchUsers”.
在这里,您将找到“ fetchUsers”方法,在此我们称为REST API端点,并将数据转换为Go结构,该结构位于models / user.go中 。 我们的“用户”字段将从“ fetchUsers”返回用户切片。
In the “users” field declaration we specified the type we expect to receive from this GraphQL resource: graphql.NewList(userObject). We told GraphQL we’re returning multiple users. The userObject is one of our GraphQL resources and you can view it in full here. It’s too much code to inline here, so I’ve linked it up to the exact line you need in the source code. The userObject itself also contains fields and nested objects ( address and company). These nested objects are linked to the exact line as well. As you can see, objects can be nested within nested objects.
在“用户”字段声明中,我们指定了希望从该GraphQL资源接收的类型:graphql.NewList(userObject)。 我们告诉GraphQL我们要返回多个用户。 userObject是我们的GraphQL资源之一,您可以在此处完整查看它 。 这里要内联的代码太多,因此我已将其链接到源代码中所需的确切行。 userObject本身还包含字段和嵌套对象( 地址和公司 )。 这些嵌套对象也链接到确切的行。 如您所见,对象可以嵌套在嵌套对象中。
Now that we’ve specified all fields and we can retrieve data from the REST API, it’s time to give our new GraphQL resource a try. Follow the setup steps (there are only 4, and they’re easy) and try to execute the following GraphQL query:
现在,我们已经指定了所有字段,并且可以从REST API检索数据,是时候尝试一下我们的新GraphQL资源了。 按照设置步骤 (只有4个,而且很简单),然后尝试执行以下GraphQL查询:
You should now see all of your users appear in the response, but only the fields we’ve specified in our query:
现在,您应该看到所有用户都出现在响应中,但是只有我们在查询中指定的字段:
I’ve redacted the rest of the users to not make this snippet too long. As you can see, only the requested fields we’re returned, as we expect from GraphQL.
我已将其余用户删除,以免使该代码段过长。 如您所见,正如GraphQL所期望的那样,仅返回了请求的字段。
获取单个用户 (Fetching a single user)
Now that we’ve seen we can retrieve all users, we’ll also go into retrieving a single user. The userObject is the same as we’ve looked at before, so I won’t go over that again, but the field declaration for “user” has changed a little bit compared to “users” and so has the query. Let’s look a the field declaration first. It’s located at queries/user.go and looks like this:
既然我们已经看到可以检索所有用户,那么我们还将继续检索单个用户。 userObject与我们之前看过的相同,因此我不再赘述,但是与“ users”相比,“ user”的字段声明有所更改,因此查询也是如此。 首先让我们看一下字段声明。 它位于querys / user.go上 ,如下所示:
There are three main differences:
有三个主要区别:
- The type we expect is now userObject instead of graphql.NewList(userObject). We only expect 1 user. 我们现在期望的类型是userObject而不是graphql.NewList(userObject)。 我们只希望有1位用户。
- Our field declaration has an Args key. We use this to tell the server that we need a user ID for this query and that it cannot be empty: graphql.NewNonNull(graphql.Int) 我们的字段声明有一个Args键。 我们使用它来告诉服务器我们需要此查询的用户ID,并且它不能为空:graphql.NewNonNull(graphql.Int)
- We pass the user ID to the fetchSingleUser method and append it to the REST endpoint 我们将用户ID传递给fetchSingleUser方法,并将其附加到REST端点
I mentioned that the GraphQL query now has changed as well, so let’s look at what it looks like:
我提到了GraphQL查询现在也发生了变化,因此让我们看一下它的外观:
This query needs a user_id to be submitted (of type Int!), so we can do that using {“user_id”: 1}, or whichever user_id you want to retrieve from the API endpoint.
此查询需要提交一个user_id(类型为Int!),因此我们可以使用{“ user_id”:1}或您要从API端点检索的任何user_id进行提交。
This query results in the following response:
此查询导致以下响应:
As you can see, we now only have the user with ID of 1.
如您所见,我们现在只有ID为1的用户。
结论 (Conclusion)
This guide has shown you how to can create an API Gateway using GraphQL, to create an abstraction layer in front of your existing REST API endpoints. There are a few things missing, like Authentication, a DataLoader for efficient data fetching, but this is a simple example to show how this works. Using this method, you can piece by piece expand your API Gateway in GraphQL and Go to cover your entire list of REST API endpoints, without disturbing your existing customers. Your existing customers will still be able to fetch data from your REST API, but over time you can help them migrate to your easy-to-use GraphQL API Gateway.
本指南向您展示了如何使用GraphQL创建API网关,以在现有REST API端点的前面创建抽象层。 缺少一些东西,例如身份验证(Authentication),它是一种用于高效获取数据的DataLoader,但这是一个简单的示例来说明其工作原理。 使用此方法,您可以在GraphQL和Go中逐步扩展API网关,以覆盖整个REST API端点列表,而不会打扰现有客户。 您现有的客户仍然可以从REST API中获取数据,但是随着时间的流逝,您可以帮助他们迁移到易于使用的GraphQL API Gateway。
Posted on: August 26th, 2020
发表于:2020年8月26日
Originally published at https://roelofjanelsinga.com.
最初发布于 https://roelofjanelsinga.com 。
翻译自: https://itnext.io/graphql-centralize-existing-rest-api-endpoints-for-easier-development-abd7b007d7c4
graphql和rest