sofa graphql 2 rest api 试用
大部分代码还是来自sofa 的官方文档,同时添加了docker && docker-compose集成
备注: 代码使用typescript 同时运行的时候为了方便直接运行使用ts-node 运行
环境准备
- docker-compose 文件
version: "3"
services:
api:
build: ./
image: dalongrong/sofa-graphql2rest
ports:
- "4000:4000"
- dockerfile
FROM node:alpine
WORKDIR /server
COPY . /server
RUN yarn install
CMD ["yarn", "start"]
代码说明
- package.json 依赖包
{
"name": "sofa-graphql2rest",
"version": "1.0.0",
"license": "MIT",
"main": "server.js",
"scripts": {
"start": "ts-node index.ts"
},
"dependencies": {
"body-parser": "1.18.3",
"chalk": "2.4.2",
"express": "4.16.4",
"express-graphql": "0.7.1",
"graphql": "^14.0.2",
"graphql-subscriptions": "^1.0.0",
"graphql-tag": "2.10.0",
"graphql-tools": "4.0.3",
"sofa-api": "^0.2.2",
"swagger-ui-express": "4.0.2"
},
"devDependencies": {
"@types/swagger-ui-express": "3.0.0",
"@types/body-parser": "1.17.0",
"@types/express": "4.16.0",
"@types/express-graphql": "0.6.2",
"@types/graphql": "14.0.3",
"esm": "^3.0.84",
"ts-loader": "^5.3.3",
"ts-node": "7.0.1",
"typescript": "3.2.2"
}
}
- graphql api 开发
基于graphql-tools,同时集成express-graphql 以及swagger open api 文档
graphql schema 定义 type.ts
import gql from 'graphql-tag';
export const typeDefs = gql`
type Pizza {
dough: String!
toppings: [String!]
}
type Salad {
ingredients: [String!]!
}
union Food = Pizza | Salad
type Book {
id: ID!
title: String!
}
type User {
id: ID!
name: String!
favoritePizza: Pizza!
favoriteBook: Book!
favoriteFood: Food!
shelf: [Book!]!
}
type Post {
comments(filter: String!): [String!]
}
type Query {
me: User
user(id: ID!): User
users: [User!]
usersLimit(limit: Int!): [User!]
usersSort(sort: Boolean!): [User!]
book(id: ID!): Book
books: [Book!]
never: String
feed: [Post]
}
type Mutation {
addBook(title: String!): Book
}
type Subscription {
onBook: Book
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
`;
resolvers 定义 resolvers.ts 同时集成了subscription
import { PubSub } from 'graphql-subscriptions';
const pubsub = new PubSub();
import {
UsersCollection,
BooksCollection,
PostsCollection,
} from './collections';
const BOOK_ADDED = 'BOOK_ADDED';
export const resolvers: any = {
Query: {
me() {
return UsersCollection.get(1);
},
user(_: any, { id }: any) {
return UsersCollection.get(id);
},
users() {
return UsersCollection.all();
},
usersLimit(_: any, { limit }: any) {
return UsersCollection.all().slice(0, limit);
},
usersSort(_: any, { sort }: any) {
const users = UsersCollection.all();
return sort ? users.sort((a, b) => b.id - a.id) : users;
},
book(_: any, { id }: any) {
return BooksCollection.get(id);
},
books() {
return BooksCollection.all();
},
feed() {
return PostsCollection.all();
},
},
Mutation: {
addBook(_: any, { title }: any) {
const book = BooksCollection.add(title);
pubsub.publish(BOOK_ADDED, { onBook: book });
return book;
},
},
Subscription: {
onBook: {
subscribe: () => pubsub.asyncIterator([BOOK_ADDED]),
},
},
Food: {
__resolveType(obj: any) {
if (obj.ingredients) {
return 'Salad';
}
if (obj.toppings) {
return 'Pizza';
}
return null;
},
},
Post: {
comments(post: { comments: string[] }, { filter }: { filter: string }) {
return post.comments.filter(
comment =>
!filter || comment.toLowerCase().indexOf(filter.toLowerCase()) > -1
);
},
},
};
代码入口
index.ts
import * as express from 'express';
import { makeExecutableSchema } from 'graphql-tools';
import * as bodyParser from 'body-parser';
import * as useGraphQL from 'express-graphql';
import * as swaggerUi from 'swagger-ui-express';
import chalk from 'chalk';
import { resolve } from 'path';
import { typeDefs } from './types';
import { resolvers } from './resolvers';
import * as swaggerDocument from './swagger.json';
// Sofa
import sofa, { OpenAPI } from 'sofa-api';
import { logger } from 'sofa-api/dist/logger';
const app = express();
app.use(bodyParser.json());
const schema = makeExecutableSchema({
typeDefs,
resolvers: resolvers as any,
});
const openApi = OpenAPI({
schema,
info: {
title: 'Example API',
version: '3.0.0',
},
});
app.use(
sofa({
schema,
ignore: ['User.favoriteBook'],
onRoute(info) {
openApi.addRoute(info, {
basePath: '',
});
},
})
);
openApi.save(resolve(__dirname, './swagger.json'));
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.use('/webhook', (req, res) => {
logger.info('Received a webhook', req.body);
res.statusCode = 200;
res.statusMessage = 'OK';
res.send();
});
app.use(
'/graphql',
useGraphQL({
schema,
graphiql: true,
})
);
const port = 4000;
app.listen(port, () => {
const url = `http://localhost:${4000}`;
function printUrl(path: string) {
return chalk.gray(url + path);
}
console.log(`
${chalk.bold('GraphQL:')} ${printUrl('/graphql')}
${chalk.bold('Queries:')}
me: ${printUrl('/me')}
users: ${printUrl('/users')}
user: ${printUrl('/user/1')}
books: ${printUrl('/books')}
book: ${printUrl('/book/1')}
${chalk.bold('Mutations:')}
addBook: ${printUrl('/add-book')} ${chalk.italic.gray(
'POST: {title}'
)}
`);
});
运行&&测试
- 运行
docker-compose build && docker-compose up -d
- 效果
openapi docs
http://localhost:4000/docs
graphql ui graphiql 工具
http://localhost:4000/graphql

- 查询执行
rest api
graphql api

说明
sofa 在设计上充分graphql 的ast 语法,同时集成了open api ,同时按照设计的方案,可以集成比较多的graphql 的平台,主要是scema
参考资料
https://github.com/rongfengliang/sofa-graphql2rest-docker-compose
https://sofa-api.com/
https://github.com/Urigo/sofa
sofa graphql 2 rest api 试用的更多相关文章
- sofa graphql 2 rest api webhook 试用
sofa 的webhook实际上就是将graphql 的subscription 进行了扩展,当接受到sub 请求的时候 再做一次http 的转发处理,方便rest api 的访问 环境准备 环境还是 ...
- sofa graphql 2 rest api框架
sofa 是一个出发点不一样的工具,提供了从graphql 2 rest 的处理,一般现有的框架都在 关注的是rest 2 graphql (大部分还是基于swagger.open api 标准进行设 ...
- 记一次通过c#运用GraphQL调用Github api
阅读目录 GraphQL是什么 .net下如何运用GraphQL 运用GraphQL调用Github api 结语 一.Graphql是什么 最近在折腾使用Github api做个微信小程序练练手,本 ...
- 人人都是 API 设计师:我对 RESTful API、GraphQL、RPC API 的思考
原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. 有一段时间没怎么写文章了,今天提笔写一 ...
- minio select api 试用
对于minio 我们可以使用基于sql 的对象内容查询,特别适合进行特定文件内容的获取,强大方便. 以下是一个简单的试用 环境准备 集成了prometheus docker-compose 文件 ...
- 百度地图API试用--(初次尝试)
2016-03-17: 百度地图API申请key的步骤相对简单,不做过多阐述. 初次使用百度地图API感觉有点神奇,有些功能加进来以后有点问题,注释掉等有空再解决. 代码如下: <%@ page ...
- hasura graphql server event trigger 试用
hasura graphql server 是一个很不错的graphql 引擎,当前版本已经支持event triiger 了 使用此功能我们可以方便的集成webhook功能,实现灵活,稳定,快捷的消 ...
- haproxy 2.0 dataplaneapi rest api 试用
我们可以基于haproxy 提供的dataplaneapi 动态进行haproxy 配置的修改,增强haproxy的可编程能力,以下是一个简单 的测试,基于docker-compose运行 环境准备 ...
- haproxy 2.0 dataplaneapi rest api 转为graphql
haproxy 2.0 dataplaneapi rest api 是比较全的,以下是一个简单的集成graphql,通过swagger-to-graphql 转换为graphql api 方便使用 环 ...
随机推荐
- SecureCRT使用(转)
功能介绍 连接概述 1.当您启动SecureCRT时,您将看到“快速连接”对话框与主SecureCRT窗口一起出现. 2.有几种接口可用于连接远程机器:快速连接对话框,工具栏上的连接栏,会 ...
- libusb示例
#include <stdio.h> #include <libusb-1.0/libusb.h> #include <stdint.h> #include < ...
- MySQL:数据库的基本操作
第二篇.数据库的基本操作 一.创建数据库 附:创建数据库并不意味输入数据在这个数据库中,只有用切换数据库才可以输数据到这个数据库中. 1.创建数据库 格式:create database数据库名字 [ ...
- Day14作业及默写
1.整理今天所学内容,整理知识点,整理博客. pass 2.画好流程图. pass 3.都完成的做一下作业(下面题都是用内置函数或者和匿名函数结合做出): pass 4.用map来处理字符串列表,把列 ...
- jQuery中extend()实现原理
jQuery.extend使用的几种方式 1.jQuery.extend(源对象) jQuery源代码: if(length == i){ target = this; --i; } 示例1: var ...
- 3--Selenium环境准备--Eclipse 引入 selenium-server包
1.下载selenium-server包 selenium-server-standalone包是Seleniumd的核心jar包,其中包含了各种元素定位和调用浏览器的方法.下载jar包后,在ID ...
- Access denied for user 'root'@'IP' (using password:YES)解决方法
在MySql的使用过程中,碰到“Access denied for user 'root'@'IP' (using password:YES)”的问题,使用以下语句修改后还是不行. GRANT ALL ...
- iOS原生和React-Native之间的交互2
今天看下iOS原生->RN: 这里有个问题: * 我这里只能通过rn->ios->rn来是实现* 如果想直接ios-rn 那个iOS中的CalendarManager的self.br ...
- 【Python】Excel操作-2 (07版本以下Excel操作,其实不怎么用了,麻蛋,预习了2天课间才发现,还说怎么跟老师讲的不一样)
#保存修改Excel import xlrd from xlutils.copy import copy #打开Excel文档并将内容读取到内存 readbook=xlrd.open_workbook ...
- socket 聊天室实现
server #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket ...