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 方便使用 环 ...
随机推荐
- 201621123001 《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 关于泛型 <T extends Comparable <T ...
- 内存布局:栈,堆,BSS段(静态区),代码段,数据段
简介 我们程序运行的时候都是放在内存里的.根据静态.成员函数.代码段.对象.等等.放在不同的内存分块里.大概分为5块 1 栈 2 堆 3 BSS段-全局区-(静态区) 4 代码段 5 数据段 栈 ...
- vue-cli快速构建vue项目模板
vue-cli 是vue.js的脚手架,用于自动生成vue.js模板工程的. 1.使用npm安装vue-cli 需要先装好vue 和 webpack(前提是已经安装了nodejs,否则连npm都用不了 ...
- Effective Java Methods Common to All Objects
Obey the general contract when overriding equals 先了解equals 和 == 的区别,如果不重写equals, equals比较的仅仅只是是否引用同一 ...
- ESP8266 上线
1.首先配置esp8266 WIFI模块 使用USB转 TTL 连接 esp8266 WIFI模块,波特率115200 //查询固件版本 AT+GMR //设置WiFi应用模式为Station AT+ ...
- 字符界面的贪吃蛇--链表--C++
前天看了下链表,由于平时对链表的使用不多,所以对链表的应用也没什么了解,所以想来想去,就想用链表实现一下贪吃蛇. 下面言归正传,先看效果图,再看代码,其他没有了! 图1: 图2: 代码: #inclu ...
- ios轮播图片用法
// // ZQRViewController.m // 04-图片轮播器 // // Created by apple on 17-08-24. // Copyright (c) 2017年 zzq ...
- scrapy爬取动态分页内容
1.任务定义: 爬取某动态分页页面中所有子话题的内容. 所谓"动态分页":是指通过javascript(简称"js")点击实现翻页,很多时候翻页后的页面地址ur ...
- mongoDB安装windows 64 bit
mongoDB安装windows 64 bit https://www.mongodb.org/downloads?_ga=1.207888916.746558625.1410501054 下载, ...
- NOI-1.1-08-字符三角形
08:字符三角形 总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个字符,用它构造一个底边长5个字符,高3个字符的等腰字符三角形. 输入 输入只有一行, 包含一个字符. 输出 ...