冠军

导航

Fake JSON Server

Fake JSON Server

https://github.com/ttu/dotnet-fake-json-server

Fake JSON Server 是 Fake REST API,可以作为原型来模拟后端 API,活着临时用于 CRUD 的后端。Fake JSON Server 可以作为体验版的 GraphQL 查询和变化支持。

  • 不需要定义资源类型,直接使用动态类型
  • 不需要定义路由,路由动态处理
  • 不需要数据库,数据保存在单个 JSON 文件中
  • 不需要准备,只需要启动该服务器,API 就可以用于任何数据

为什么要使用它来替代其他的 Fake 服务器?

  1. 使用最佳实践来构建 API,当构建你的 API 的时候,可以作为参考时限。
  2. 可以运行在 Windows、Linux 和 macOS 平台上,而不需要任何的安装或者预先的执行,或者 Docker 环境
  3. 功能列表如下

功能

  • 支持的 HTTP 方法
    • 所有的 CRUD 操作 (GET、PUT、POST、PATCH、DELETE)
    • 用来提取资源的方法 (HEAD、OPTIONS)
  • 针对长时间的更新操作与查询提供的异步版本
  • REST API 遵循多个来源的最佳实践
    • 使用正确的状态吗、头部等等
    • 由于各种最佳实践都有一点区别,这些冲突的地方基于你的观点
  • Token、Basic 和 API Key 认证方式支持
  • WebSocket 更新提示
  • 针对查询的延迟与错误的仿真
  • 静态文件支持
  • Swagger 支持
  • CORS
  • 内容协商 (输出格式:JSON、CSV 与 XML)
  • 使用 ETag 缓存并避免空中碰撞
  • 可配置的定制化响应转换
  • 体验版的 GraphQL 查询与修改支持

开发

  • 使用 .NET 5
  • 使用 JSON Flat File Data Store 来存储数据
  • 可以安装微 dotnet 全局工具使用
  • 可以不安装 .NET 就使用
    • 使用 Docker
    • 编译微自包含应用

目录

入门

使用 .NET CLI 启动

# Get source code from GitHub
$ git clone https://github.com/ttu/dotnet-fake-json-server.git

$ cd dotnet-fake-json-server/FakeServer
$ dotnet run

使用预先定义的数据文件和 url 启动服务器 ( 参数 )

# Optional arguments:
#   --file <FILE>    Data store's JSON file (default datastore.json)
#   --urls <URL>     Server url (default http://localhost:57602)      
#   --serve <PATH>   Serve static files (default wwwroot)
#   --version        Prints the version of the app

$ dotnet run --file data.json --urls http://localhost:57602

安装为 .NET 全局工具

本服务器可以安装成 dotnet 全局工具。设置并保存文件到 %USERPROFILE%.dotnet\tools (Windows), $HOME/.dotnet/tools (Linux/macOS).。作为默认数据存储的 JSON 文件将被创建到执行目录中。

# install as a global tool
$ dotnet tool install --global FakeServer

# Example: Start server
$ fake-server --file data.json --urls http://localhost:57602

# Update to the newest version
$ dotnet tool update --global FakeServer

Docker

如果你的机器没有安装 .NET,可以通过 Docker 来使用。

# Get source code from GitHub
$ git clone https://github.com/ttu/dotnet-fake-json-server.git

$ cd dotnet-fake-json-server
$ docker build -t fakeapi .

# Run in foreground
$ docker run -it -p 57602:57602 --name fakeapi fakeapi

# Run in detached mode (run in background)
$ docker run -it -d -p 57602:57602 --name fakeapi fakeapi

# Start stopped container (remove -a to run in background)
$ docker start -a fakeapi

将 JSON 文件复制到/复制出 Docker 容器,文件名为 datastore.json。

# Copy file from host to container
$ docker cp datastore.json fakeapi:/app/datastore.json

# Copy file from container to host
$ docker cp fakeapi:/app/datastore.json datastore.json
111

自包含应用

作为自包含的应用,其中包含了 Fake JSON Server 本身,.NET 运行时,和所有需要的第三方依赖。不需要安装,也不需要预先设置。

  1. 访问 最新发布版本
  2. 根据你的操作系统下载对应版本
  3. 解压并执行

例如下载 macOS 的 0.11.0 版本

$ mkdir FakeServer && cd FakeServer
$ wget https://github.com/ttu/dotnet-fake-json-server/releases/download/0.11.0/fakeserver-osx-x64.tar.gz
$ tar -zxvf fakeserver-osx-x64.tar.gz
$ chmod +x FakeServer
$ ./FakeServer

静态文件支持

Fake Server 支持静态文件,静态文件的位置可以使用绝对路径,也可以使用相对于当前位置的相对路径。

$ dotnet run -s/--serve [fullpath/relative path]
# e.g.
$ dotnet run -s build

# Use Fake Server as a global tool
$ fake-server -s/--serve [fullpath/relative path]]
# e.g.
$ fake-server --serve c:\temp\react_app\build
$ fake-server --serve /home/user/app/dist
$ fake-server --serve ./build

当使用静态文件支持的时候,它假设用户服务于单页应用,而 REST API 将不再工作。如果还需要 API 支持,启动 Fake Server 的另外一个实例。

快速示例

# List collections (should be empty, if data.json didn't exist before)
$ curl http://localhost:57602/api

# Insert new user
$ curl -H "Content-type: application/json" -X POST -d '{ "name": "Phil", "age": 20, "location": "NY" }' http://localhost:57602/api/users/

# Insert another user
$ curl -H "Content-type: application/json" -X POST -d '{ "name": "James", "age": 40, "location": "SF" }' http://localhost:57602/api/users/

# List users
$ curl http://localhost:57602/api/users

# List users from NY
$ curl http://localhost:57602/api/users?location=NY

# Get User with Id 1
$ curl http://localhost:57602/api/users/1

...

# Add users to data.json manually

# Get all users
$ curl http://localhost:57602/api/users/
...

# Or open url http://localhost:57602/swagger/ with browser and use Swagger

示例项目

Redux TodoMVC 示例,使用 Fake JSON Server 作为后端服务。

特性

认证 Authentication

Fake REST API 支持 Token 和 BASIC 认证。

可以通过将 appsettings.json 中的 Authenticaion 中的 Enabled 设置为 false 来禁用。AuthenticationType 的类型可以是:

  • token
  • basic
  • apikey

将支持的用户名和口令添加到 Users 仿数组中,而 API Key 则使用 ApiKey 属性进行设置。

"Authentication": {
  "Enabled": true,
  "AuthenticationType": "token",
  "Users": [
      { "Username": "admin", "Password": "root" }
  ],
  "ApiKey": "abcd1234"
}

Token 认证

API 服务器提供了用来生成访问令牌的端点 /token。端点支持 content-type: multipart/form-datacontent-type: application/json。使用的用户名和密码必须来自 Users 中的 usernamepassword 字段。

获取 Token

# content-type: multipart/form-data
$ curl -X POST -H 'content-type: multipart/form-data' -F username=admin -F password=root http://localhost:57602/token

# content-type: application/json
$ curl -X POST -H 'content-type: application/json' -d '{ "username": "admin", "password": "root" }' http://localhost:57602/token

令牌还可以使用 Client Credentials 认证流方式来获得。

$ curl -X POST -d "grant_type=client_credentials&client_id=admin&client_secret=root" http://localhost:57602/token

将获得的令牌添加到 Authorization 请求头中

$ curl -H 'Authorization: Bearer [TOKEN]' http://localhost:57602/api

Token 认证还提供了登出功能支持。默认令牌是不支持无效的,所以,通过 logout 来通过将 token 加入到黑名单。

$ curl -X POST -d '' -H 'Authorization: Bearer [TOKEN]' http://localhost:57602/logout

该实现非常类似于 SimpleTokenProvider,详细内容可以参考 GitHubStormPath's blog post.

BASIC 认证

不建议在产品环境中使用 BASIC 认证,Base64 编码是可以逆向解密的。

将用户名和密码使用 Base64 编码之后,添加到 Authorization 请求头,例如:'Authorization: Basic YWRtaW46cm9vdA=='

$ curl -u admin:root http://localhost:57602/api
# -u argument creates Authorization header with encoded username and password
$ curl -H 'Authorization: Basic YWRtaW46cm9vdA==' http://localhost:57602/api

API Key 认证

API Key 使用 X-API-KEY 请求头,例如 X-API-KEY: abcd1234.

$ curl -H 'X-API-KEY: abcd1234' http://localhost:57602/api

WebSockets 支持

API 将会使用 Web Socket 发送最后更新的方法 (POST, PUT, PATCH, DELETE), Path、collection 和可选的条目 id

{ "method": "PATCH", "path": "/api/users/2", "collection": "users", "itemId": 2 }

wwwroot/index.html 中包含一个 WebSocket 的示例。

CORS

CORS 已经被弃用,并全面支持。

静态文件

GET / 返回来自 wwwroot 或者自定义的位置 的静态文件。默认文件名为 index.html。

Swagger

Swagger 配置在端点 /swagger 下。

使用 ETag 实现缓存和避免空中碰撞

缓存可以禁用:

"Caching": {
  "ETag": { 
    "Enabled": true 
  }
}

如果弃用了缓存,响应头中会添加 ETag 响应头。

$ curl -v 'http://localhost:57602/api/users?age=40'

200 OK

Headers:
ETag: "5yZCXmjhk5ozJyTK4-OJkkd_X18"

缓存不会改变的资源

如果请求包含 If-None-Match 请求头,该请求头的值将与响应体的内容相比较,如果该值与响应体的校验和匹配,那么会返回 304 Not Modified

$ curl -H "If-None-Match: \"5yZCXmjhk5ozJyTK4-OJkkd_X18\"" 'http://localhost:57602/api/users?age=40'

避免空中碰撞

如果 PUT 请求中包含 If-Match 请求头,其值将与被更新的项目相比较。如果该值匹配将要被更新的项目的校验和,那么将返回 412 Precondition Failed

内容协商

客户端可以通过 Accept 请求头来决定期望返回的表示类型。默认返回 JSON 格式 ( text/json,application/json)。

支持的协商类型是 JSON、CSV 和 XML

text/json
application/json
text/csv
text/xml
application/xml

获取 CSV 格式的所有用户

$ curl -H "Accept: text/csv" http://localhost:57603/api/users

如果提供的内容类型不被支持,将返回 406 Not Acceptable

路由、功能和示例

GET      /
POST     /token
POST     /logout
POST     /admin/reload

GET      /api
HEAD     /api
GET      /api/{collection/object}
HEAD     /api/{collection/object}
POST     /api/{collection}
GET      /api/{collection}/{id}
HEAD     /api/{collection}/{id}
PUT      /api/{collection}/{id}
PATCH    /api/{collection}/{id}
DELETE   /api/{collection}/{id}
PUT      /api/{object}
PATCH    /api/{object}
DELETE   /api/{object}
OPTIONS  /api/*

GET      /async/queue/{id}
DELETE   /async/queue/{id}
POST     /async/{collection}
PUT      /async/{collection}/{id}
PATCH    /async/{collection}/{id}
DELETE   /async/{collection}/{id}
OPTIONS  /async/*

POST     /graphql

集合与对象

Fake JSON Server 被设计作为原型,所以默认支持的仅有资源是集合。

如果该 JSON 文件只有单个对象在根上,那么作为单个对象使用。

{
  "collection": [],
  "object": {}
}

路由

动态路由使用条目集合的名称和 id:api/{collection}/{id}。所有下面的示例都使用 users 作为集合名称。

如果由于某种原因,需要修改 /api 或者 /async ,通过 Config.cs 中的 ApiRoute 或者 AsyncRoute 来实现。

public class Config
{
    public const string ApiRoute = "api";
    public const string AsyncRoute = "async";
    public const string GraphQLRoute = "graphql";
    public const string TokenRoute = "token";
    public const string TokenLogoutRoute = "logout";
}

例如,如果不希望使用 api 前缀,那么可以通过 ApiRoute 来删除 api 前缀。

public const string ApiRoute = "";

使用

# Query with default route
$ curl 'http://localhost:57602/api/users?skip=5&take=20'
# Query with updated route
$ curl 'http://localhost:57602/users?skip=5&take=20'

标识

id 用来作为标识字段,默认的 id 字段类型为整数,POST 操作总是使用整数作为 id 的类型。

"users":[
  { "id": 1 }
],
"sensors": [
  { "id": "E:52:F7:B3:65:CC" }
]

如果使用字符串作为标识类型,那么条目必须使用 PUT 插入,并且 appsetting.json 中的 UpsertOnPut 必须设置为 true。

返回码

异步操作遵循 REST 菜谱手册。更新将返回 202,使用 Location 响应头来将条目排入队列中。队列在操作处理中将返回 200,当 job 完成,而 Location 头对新条目变化的时候,返回 303

方法的返回码遵循 REST API 教程

posted on 2022-07-16 17:28  冠军  阅读(84)  评论(0编辑  收藏  举报