fauxrpc

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2024 License: MIT Imports: 14 Imported by: 2

README

FauxRPC

FauxRPC is a powerful tool that empowers you to accelerate development and testing by effortlessly generating fake implementations of gRPC, gRPC-Web, Connect, and REST services. If you have a protobuf-based workflow, this tool could help.

Why FauxRPC?

  • Faster Development & Testing: Work independently without relying on fully functional backend services.
  • Isolation & Control: Test frontend components in isolation with controlled fake data.
  • Multi-Protocol Support: Supports multiple protocols (gRPC, gRPC-Web, Connect, and REST).
  • Prototyping & Demos: Create prototypes and demos quickly without building the full backend. Fake it till you make it.
  • Improved Collaboration: Bridge the gap between frontend and backend teams.
  • Plays well with others: Test data from FauxRPC will try to automatically follow any protovalidate constraints that are defined.

How it Works

FauxRPC leverages your Protobuf definitions to generate fake services that mimic the behavior of real ones. You can easily configure the fake data returned, allowing you to simulate various scenarios and edge cases. It takes in *.proto files or protobuf descriptors (in binpb, json, txtpb, yaml formats), then it automatically starts up a server that can speak gRPC/gRPC-Web/Connect and REST (as long as there are google.api.http annotations defined). Descriptors contain all of the information found in a set of .proto files. You can generate them with protoc or the buf build command.

Get Started

Install via source
go install github.com/sudorandom/fauxrpc/cmd/fauxrpc@latest
Pre-built binaries

Binaries are built for several platforms for each release. See the latest ones on the releases page.

Using Descriptors

Make an example.proto file (or use a file that already exists):

syntax = "proto3";

package greet.v1;

message GreetRequest {
  string name = 1;
}

message GreetResponse {
  string greeting = 1;
}

service GreetService {
  rpc Greet(GreetRequest) returns (GreetResponse) {}
}

Create a descriptors file and use it to start the FauxRPC server:

$ buf build ./example.proto -o ./example.binpb
$ fauxrpc run --schema=./example.binpb
2024/08/17 08:01:19 INFO Listening on http://127.0.0.1:6660
2024/08/17 08:01:19 INFO See available methods: buf curl --http2-prior-knowledge http://127.0.0.1:6660 --list-methods

Done! It's that easy. Now you can call the service with any tooling that supports gRPC, gRPC-Web, or connect. So buf curl, grpcurl, Postman, Insomnia all work fine!

$ buf curl --http2-prior-knowledge http://127.0.0.1:6660/greet.v1.GreetService/Greet
{
  "greeting":  "3 wolf moon fashion axe."
}
Using Server Reflection

If there's an existing gRPC service running that you want to emulate, you can use server reflection to start the FauxRPC service:

$ fauxrpc run --schema=https://demo.connectrpc.com
From BSR (Buf Schema Registry)

Buf has a schema registry where many schemas are hosted. Here's how to use FauxRPC using images from the registry.

$ buf build buf.build/bufbuild/registry -o bufbuild.registry.json
$ fauxrpc run --schema=./bufbuild.registry.json

This will start a fake version of the BSR API by downloading descriptors for bufbuild/registry from the BSR and using them with FauxRPC. Very meta.

Multiple Sources

You can define this --schema option as many times as you want. That means you can add services from multiple descriptors and even mix and match from descriptors and from server reflection:

$ fauxrpc run --schema=https://demo.connectrpc.com --schema=./example.binpb

What does the fake data look like?

You might be wondering what actual responses look like. FauxRPC's fake data generation is continually improving so these details might change as time goes on. It uses a library called fakeit to generate fake data. Because protobufs have pretty well-defined types, we can easily generate data that technically matches the types. This works well for most use cases, but FauxRPC tries to be a little bit better. If you annotate your protobuf files with protovalidate constraints, FauxRPC will try its best to generate data that matches these constraints. Let's look at some examples!

syntax = "proto3";

package greet.v1;

message GreetRequest {
  string name = 1;
}

message GreetResponse {
  string greeting = 1;
}

service GreetService {
  rpc Greet(GreetRequest) returns (GreetResponse) {}
}

With FauxRPC, you will get any kind of word, so it might look like this:

{
  "greeting": "Poutine."
}

This is fine, but for the RPC, we know a bit more about the type being returned. We know that it sends a greeting back that looks like "Hello, [name]". So here's what the same protobuf file might look like with protovalidate constraints:

Now let's see what this looks like with protovalidate constraints:

syntax = "proto3";

import "buf/validate/validate.proto";

package greet.v1;

message GreetRequest {
  string name = 1 [(buf.validate.field).string = {min_len: 3, max_len: 100}];
}

message GreetResponse {
  string greeting = 1 [(buf.validate.field).string.pattern = "^Hello, [a-zA-Z]+$"];
}

service GreetService {
  rpc Greet(GreetRequest) returns (GreetResponse) {}
}

With this new protobuf file, this is what FauxRPC might output now:

{
  "greeting": "Hello, TWXxF"
}

In essence, protovalidate constraints enable FauxRPC to generate more realistic and contextually relevant fake data, aligning it closer to the expected behavior of your actual services.

Status: Alpha

This project is just starting out. I plan to add a lot of things that make this tool actually usable in more situations.

  • Service for adding/updating/removing stub responses with a CLI to add/remove/replace these stubs
  • Configuration file
  • BSR Support (this is a 'maybe' because using buf build to emit descriptors works well enough IMO)
  • Testing for REST translations. I have no idea if this actually works yet
  • Better streaming support. FauxRPC does work with streaming calls but it only returns a single response

Documentation

Index

Constants

View Source
const MaxNestedDepth = 20

Variables

This section is empty.

Functions

func GenerateBytes

func GenerateBytes(faker *gofakeit.Faker, hints BytesHints) []byte

func GenerateFixed32

func GenerateFixed32(faker *gofakeit.Faker, hints Fixed32Hints) uint32

func GenerateFixed64

func GenerateFixed64(faker *gofakeit.Faker, hints Fixed64Hints) uint64

func GenerateFloat32

func GenerateFloat32(faker *gofakeit.Faker, hints Float32Hints) float32

func GenerateFloat64

func GenerateFloat64(faker *gofakeit.Faker, hints Float64Hints) float64

func GenerateInt32

func GenerateInt32(faker *gofakeit.Faker, hints Int32Hints) int32

func GenerateInt64

func GenerateInt64(faker *gofakeit.Faker, hints Int64Hints) int64

func GenerateSFixed64

func GenerateSFixed64(faker *gofakeit.Faker, hints SFixed64Hints) int64

func GenerateSFixedInt32

func GenerateSFixedInt32(faker *gofakeit.Faker, hints SFixedInt32Hints) int32

func GenerateSInt32

func GenerateSInt32(faker *gofakeit.Faker, hints SInt32Hints) int32

func GenerateSInt64

func GenerateSInt64(faker *gofakeit.Faker, hints SInt64Hints) int64

func GenerateString

func GenerateString(faker *gofakeit.Faker, hints StringHints) string

func GenerateUInt32

func GenerateUInt32(faker *gofakeit.Faker, hints UInt32Hints) uint32

func GenerateUInt64

func GenerateUInt64(faker *gofakeit.Faker, hints UInt64Hints) uint64

func NewDataGenerator

func NewDataGenerator() *dataGenerator

Types

type BytesHints

type BytesHints struct {
	Rules     *validate.BytesRules
	FirstName bool
	LastName  bool
	Name      bool
	UUID      bool
	URL       bool
	Version   bool
}

type DataGenerator

type DataGenerator interface {
	SetData(msg *dynamicpb.Message)
}

type Fixed32Hints

type Fixed32Hints struct {
	Rules *validate.Fixed32Rules
}

type Fixed64Hints

type Fixed64Hints struct {
	Rules *validate.Fixed64Rules
}

type Float32Hints

type Float32Hints struct {
	Rules *validate.FloatRules
}

type Float64Hints

type Float64Hints struct {
	Rules *validate.DoubleRules
}

type Int32Hints

type Int32Hints struct {
	Rules *validate.Int32Rules
}

type Int64Hints

type Int64Hints struct {
	Rules *validate.Int64Rules
}

type SFixed64Hints

type SFixed64Hints struct {
	Rules *validate.SFixed64Rules
}

type SFixedInt32Hints

type SFixedInt32Hints struct {
	Rules *validate.SFixed32Rules
}

type SInt32Hints

type SInt32Hints struct {
	Rules *validate.SInt32Rules
}

type SInt64Hints

type SInt64Hints struct {
	Rules *validate.SInt64Rules
}

type StringHints

type StringHints struct {
	Rules     *validate.StringRules
	FirstName bool
	LastName  bool
	Name      bool
	UUID      bool
	URL       bool
	Version   bool
}

type UInt32Hints

type UInt32Hints struct {
	Rules *validate.UInt32Rules
}

type UInt64Hints

type UInt64Hints struct {
	Rules *validate.UInt64Rules
}

Directories

Path Synopsis
cmd
fauxrpc command
example
private

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL