2 个不稳定版本

0.2.0 2024年2月18日
0.1.0 2023年2月25日

11#json-response

MIT 协议

25MB
2K SLoC

包含 (ELF 库, 9.5MB) _plugins/librandom_product_code.so, (ELF 库, 7.5MB) _plugins/librnd_vehicleid.so, (ELF 库, 4MB) _plugins/libtest_plugin.so, (ELF 可执行文件/库, 5.5MB) binary/fips, (ELF 库, 3.5MB) _plugins/libpluginname.so, (rust 库, 180KB) binary/libfips.rlib

假数据注入代理服务器 - 简称 Fips - 快速实现模拟和代理

License: MIT

关于

Fips 提供了三种不同的功能:它可以作为一个假数据服务器,也可以作为一个简单的代理服务器,还可以两者结合,即时操作响应 - 由您自己的规则定义。因此,如果您希望快速设置端点并在应用程序中测试它,Fips 是最佳选择 - 后端工作目前被阻塞?没问题。启动应用程序并托管一个模拟端点,同时将您的其他端点代理到实际后端。

安装

  • 安装 rust 和 cargo
  • 检出此仓库。
  • 进入它并运行 cargo run - 或者如果您希望生成可执行文件,运行 cargo build

命令行参数

另请参阅 fips(.exe) --help

  # Start fips on this port
  --port: 8888
  # Load plugins from this directory, detault is the current directory.
  --plugins: .
  # Load configuration files from this directory. default is the current directory.
  --config: .

快捷键

Tab 切换到下一个标签
Shift+ Tab 切换到上一个标签
c 清除日志输出
r 重新加载配置文件
Esc 退出

用法

Fipss 配置放在 .yaml.yml 文件中。它们在启动时从 --config 目录加载。对于每个请求,Fips 都会检查配置文件,看是否有任何配置对象与当前请求 URI 匹配。如果匹配,则根据配置明确应用四种模式之一。

请注意以下事项:

  • Fips 使用正则表达式来匹配路径。配置路径中的 /foo/bar 也会匹配 /foo/bar/baz,因此如果您关心这一点,则需要尽可能具体。
  • 如果多个规则匹配,则只应用第一个匹配的规则。
  • 规则按照出现的顺序应用 - 顺序很重要!
  • 配置文件不检查拼写,如果因为拼写/缩进错误无法读取配置文件,服务器将崩溃。为了支持您创建配置,fips提供了一个JSON模式。您可以使用--write-schema命令行参数创建它。请参阅vscode json-schema的设置(点击查看)vscode yaml-schema的设置(点击查看),了解如何将vscode指向创建的模式文件。
  • 对象操作使用dotpath crate。语法如下。

示例配置在config.yaml

有关更多示例配置,请参阅examples目录。

  1. 任何到达Fips的URI为/foo/bar的请求将返回['this is a lot of fun']
- Mock:
    path: ^/foo/bar/$
    rules:
      - path: 
        item: ['this is a lot of fun']
  1. 任何针对/foo/*anything*/bar/的请求将被代理到localhost:4041的服务器,将转发Authorization头。
- Proxy:
    path: ^/foo/.*/bar/$
    forwardUri: 'https://127.0.0.1:4041'
    forwardHeaders:
      - 'Authorization'
  1. 任何针对/foo/*anything*/bar/的请求将被代理到localhost:4041的服务器,将返回content-type头。最后我们将在响应中追加另一个user
- Fips: 
    path: ^/foo/.*/bar/$
    forwardUri:
      "https://127.0.0.1:4041"
    backwardHeaders:
      - "content-type"
    rules:
      - path: ">>"
      {
        "firstname": "Morty",
        "lastname": "Smith",
        "status": "cloned himself"
      }

每个规则类型的所有配置参数

Fips函数(模拟和代理组合)的配置选项

    # A a regex to match incoming requests. if a match is found, this rule will be applied
    path: String
    # This name will be displayed for debugging purposes
    name: String
    # Sleep for ms
    sleep: u64
    # Add these headers to the response
    headers: HashMap<String, String>,
    # Only apply a rule if the method matches these
    matchMethods: Vec<String>
    # Only apply a rule with this probability. It's best to have a fallback rule defined
    matchProbability: Option<f32>
    # Only apply a rule if the request body contains the given string
    matchBodyContains: Option<String>
    # Forward any incoming request to this uri and return the response
    forwardUri: String
    # Forward matching headers on the request
    forwardHeaders: Vec<String>
    # Return these headers from the original response
    backwardHeaders: Vec<String>,
    # Set the response status 
    responseStatus: u16 
    # Apply these transformations on the response (see rules further below)
    rules: Vec<Rules>

代理函数的配置选项

    # A a regex to match incoming requests. if a match is found, this rule will be applied
    path: String
    # This name will be displayed for debugging purposes
    name: String
    # Sleep for ms
    sleep: u64
    # Add these headers to the response
    headers: HashMap<String, String>,
    # Only apply a rule if the method matches these
    matchMethods: Vec<String>
    # Only apply a rule with this probability. It's best to have a fallback rule defined
    matchProbability: Option<f32>
    # Only apply a rule if the request body contains the given string
    matchBodyContains: Option<String>
    # Forward any incoming request to this uri and return the response
    forwardUri: String
    # Forward matching headers on the request
    forwardHeaders: Vec<String>
    # Return these headers from the original response
    backwardHeaders: Vec<String>,

模拟函数的配置选项

    # A a regex to match incoming requests. if a match is found, this rule will be applied
    path: String
    # This name will be displayed for debugging purposes
    name: String
    # Sleep for ms
    sleep: u64
    # Add these headers to the response
    headers: HashMap<String, String>,
    # Only apply a rule if the method matches these
    matchMethods: Vec<String>
    # Only apply a rule with this probability. It's best to have a fallback rule defined
    matchProbability: Option<f32>
    # Only apply a rule if the request body contains the given string
    matchBodyContains: Option<String>
    # Forward any incoming request to this uri and return the response
    forwardUri: String
    # Set the response status 
    responseStatus: u16 
    # Add these items to the response body
    body: Serde<Value>

托管静态文件的配置选项

    # A a regex to match incoming requests. if a match is found, this rule will be applied
    path: String
    # This name will be displayed for debugging purposes
    name: String
    # Sleep for ms
    sleep: u64
    # Add these headers to the response
    headers: HashMap<String, String>,
    # Only apply a rule if the method matches these
    matchMethods: Vec<String>
    # Only apply a rule with this probability. It's best to have a fallback rule defined
    matchProbability: Option<f32>
    # Only apply a rule if the request body contains the given string
    matchBodyContains: Option<String>
    # host files from this directory
    staticBaseDir: String

规则

   # The json_dotpath (see more at Object manipulation on the response)
   path: String,
   # Any json serializeable item that is added to the response at the paths location
   item: Serde<Value>

响应上的对象操作

{
  "fruit": [
    { "name": "lemon", "color": "yellow" },
    { "name": "apple", "color": "green" }
  ]
}
  • "" ... 整个对象
  • "fruit" ... 水果数组
  • "fruit.0" ... 第一个水果对象,{"name": "lemon", "color": "yellow"}
  • "fruit.1.name" ... 第二个(索引从0开始)水果的名称,"apple"
  • < ... 第一个元素
  • > ... 最后一个元素
  • - 或 << ... 预先添加
  • + 或 >> ... 追加
  • <n, 例如 <5 ... 在第n个元素之前插入
  • >n, 例如 >5 ... 在第n个元素之后插入

扩展

Fipss的一个重要特性是其扩展系统。Fips导出Rust宏export_plugin。您的扩展可以使用此宏来注册插件。插件名称将与您的配置匹配。如果发生匹配,则模式将被替换为您的插件输出。所有与您的OS匹配的插件,在Fips二进制文件相关的plugins目录中,将自动在启动时加载。

示例插件实现

use fips::{PluginRegistrar, Function, InvocationError};
use fake::{faker::name::raw::NameWithTitle, locales::EN, Fake};
use serde_json::Value

pub struct Random;

impl Function for Random {
    fn call(&self, args: Vec<Value>) -> Result<String, InvocationError> {
        let random_fake_name: String = NameWithTitle(EN).fake();
        let json_serializable = format!("{{\"bar\": [\"{}\"]}}", random_fake_name).to_owned();
        Ok(json_serializable)
    }
}

fips::export_plugin!(register);

extern "C" fn register(registrar: &mut dyn PluginRegistrar) {
    registrar.register_function("{{Name}}", Box::new(Random));
}

上述代码在Fips插件注册表中注册了插件。当找到匹配的规则时,将匹配插件的namejson serializeable(!)的返回值将用于替换匹配规则中的模式。

示例config.yaml

- Mock:
    path: ^/randomname/$
    rules:
        body:
          foo: '{{Name}}'

示例输出为curl localhost:8888/randomname/ | jq

{
  "foo": {
    "bar": ["Ms. Destiney Metz"]
  }
}

您还可以通过配置文件传递参数给插件。如果这样做,插件必须配置为配置yaml中的对象

- Mock:
    path: ^/randomname/$
    rules:
        item:
          foo:
            plugin: '{{Name}}',
            args: [ "foo", 1, "bar" ]

示例输出为curl localhost:8888/randomname/ | jq

{
  "foo": {
    "bar": ["Ms. Destiney Metz"]
  }
}

许可

本项目的许可协议为 MIT 许可协议

依赖项

约15-27MB
约422K SLoC