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 方便使用 环 ...
随机推荐
- PHP socket以及http、socket、tcp、udp
一.TCP/UDP/Socket TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为 ...
- 【转载】ZooKeeper学习第二期--ZooKeeper安装配置
原文地址(https://www.cnblogs.com/sunddenly/p/4018459.html) 一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及 ...
- Toy Factory
Factory is a design pattern in common usage. Please implement a ToyFactory which can generate proper ...
- caffe blob
Blob,包括输入数据.输出数据.权值等: Blob是Caffe中处理和传递实际数据的数据封装包,并且在CPU与GPU之间具有同步处理能力.从数学意义上说,blob是按C风格连续存储的N维数组. ca ...
- C++基础知识:STL简介
1.标准模板库STL ― STL , 即 : Standard Template Library , 是 C++的一部分― STL是常用数据结构和算法的集合― STL的目标是标准化组件 , 提高开发效 ...
- C++基础知识:操作符重载
1.C++标准库: C++标准库并不是C++语言的一部分C++标准库是由C++语言编写而成的类库和函数的集合C++标准库中定义的类和对象都位于std命名空间中C++标准库的头文件都不带.h后缀C++标 ...
- C++四种类型之间的转换
C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a. C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. const_cas ...
- SpringMVC学习三
实现有点用处的增删改查,并利用了AJAX(javascript)动态修改,还有json的返回读取,以及文件上传和下载. 配置基础Employee类以及Dao类 package com.springmv ...
- 解析url中参数
兼容不带参数等情况 function getUrlParam(){ var params = {}; var search = location.search; search = /\?/.test( ...
- Alpha冲刺3
前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/9971198.html 作业博客:https://edu.cnblogs.com/campus/ ...