connexions

package module
v0.0.53 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2023 License: MIT Imports: 43 Imported by: 0

README

Connexions

CI Endpoint Badge License

Connexions is a library originally inspired by Connexion.
Connexion allows you to set up a REST API with Swagger documentation and OAuth2 authentication with minimal effort.

Connexions takes this one step further by allowing you to define multiple APIs not limited to only Swagger and(or) OpenAPI.
You can define single response for any arbitrary path on the fly.

Goal:

  • simplify the development process

Features:

  • Randomized response contents, allowing you to redefine the response for any path in a locale of your choice
  • Mimic error responses and status codes
  • Configurable latency in responses

Simple start:

docker run -it --rm \
  -p 2200:2200 \
  -v connexions:/app/resources \
  cubahno/connexions api

License

Copyright (c) 2023-present

Licensed under the MIT License

===================

OpenAPI Specification
OpenAPI 3.0 Style Values
Operation Object
YAML format

Documentation

Index

Constants

View Source
const (
	OpenAPIRouteType = "openapi"
	FixedRouteType   = "fixed"
)
View Source
const (
	// RootServiceName is the name and location in the service directory of the service without a name.
	RootServiceName = ".root"

	// RootOpenAPIName is the name and location of the OpenAPI service without a name.
	RootOpenAPIName = ".openapi"
)
View Source
const (
	TypeArray   = "array"
	TypeBoolean = "boolean"
	TypeInteger = "integer"
	TypeNumber  = "number"
	TypeObject  = "object"
	TypeString  = "string"
)
View Source
const (
	ParameterInPath   = "path"
	ParameterInQuery  = "query"
	ParameterInHeader = "header"
	// ParameterInBody v2 Swagger only
	ParameterInBody = "body"
)
View Source
const (
	NULL = "__null__"
)

NULL is used to force resolve to nil

Variables

View Source
var (
	ErrInvalidConfig                    = errors.New("invalid config")
	ErrServiceNotFound                  = errors.New("service not found")
	ErrResourceNotFound                 = errors.New("resource not found")
	ErrResourceMethodNotFound           = errors.New("resource method not found")
	ErrOpenAPISpecIsEmpty               = errors.New("OpenAPI spec is empty")
	ErrInvalidHTTPVerb                  = errors.New("invalid HTTP verb")
	ErrInvalidURLResource               = errors.New("invalid URL resource")
	ErrCreatingDirectories              = errors.New("error creating directories")
	ErrCreatingFile                     = errors.New("error creating file")
	ErrSavingFile                       = errors.New("error saving file")
	ErrReservedPrefix                   = errors.New("reserved prefix")
	ErrNoPathsInSchema                  = errors.New("no paths found in schema")
	ErrUnexpectedFormDataType           = errors.New("expected map[string]any for multipart/form-data")
	ErrUnexpectedFormURLEncodedType     = errors.New("expected map[string]any for x-www-form-urlencoded")
	ErrOnlyFixedResourcesAllowedEditing = errors.New("only fixed resources are allowed editing")
	ErrInternalServer                   = errors.New("internal server error")
	ErrFileUpload                       = errors.New("error uploading file")
	ErrExtractingFiles                  = errors.New("error extracting files")
	ErrReadingZipFile                   = errors.New("error reading zip file")
)
View Source
var PlaceholderRegex = regexp.MustCompile(`\{[^\}]*\}`)

Functions

func AppendSliceFirstNonEmpty

func AppendSliceFirstNonEmpty[T comparable](data []T, value ...T) []T

AppendSliceFirstNonEmpty appends the first non-empty value to the given slice.

func ApplySchemaConstraints

func ApplySchemaConstraints(openAPISchema any, res any) any

ApplySchemaConstraints applies schema constraints to the value. It converts the input value to match the corresponding OpenAPI type specified in the schema.

func CastToSchemaFormat

func CastToSchemaFormat(ctx *ReplaceContext, value any) any

func CleanupServiceFileStructure

func CleanupServiceFileStructure(servicePath string) error

CleanupServiceFileStructure removes empty directories from the service directory.

func CollectContexts

func CollectContexts(names []map[string]string, fileCollections map[string]map[string]any,
	initial map[string]any) []map[string]any

func ComposeFileSavePath

func ComposeFileSavePath(descr *ServiceDescription, paths *Paths) string

ComposeFileSavePath composes a save path for a file.

func ComposeOpenAPISavePath

func ComposeOpenAPISavePath(descr *ServiceDescription, baseDir string) string

ComposeOpenAPISavePath composes a save path for an OpenAPI specification. The resulting filename is always index.<spec extension>.

func ConditionalLoggingMiddleware

func ConditionalLoggingMiddleware(cfg *Config) func(http.Handler) http.Handler

func CopyDirectory

func CopyDirectory(src, dest string) error

CopyDirectory copies a directory recursively.

func CopyFile

func CopyFile(srcPath, destPath string) error

CopyFile copies a file from srcPath to destPath. If the destination directory doesn't exist, it will be created.

func EncodeContent

func EncodeContent(content any, contentType string) ([]byte, error)

func ExtractPlaceholders

func ExtractPlaceholders(input string) []string

ExtractPlaceholders extracts all placeholders including curly brackets from a pattern.

func ExtractZip

func ExtractZip(zipReader *zip.Reader, targetDir string, onlyPrefixes []string) error

ExtractZip extracts a zip archive to a target directory. onlyPrefixes is a list of prefixes that are allowed to be extracted.

func FixSchemaTypeTypos

func FixSchemaTypeTypos(typ string) string

FixSchemaTypeTypos fixes common typos in schema types.

func GenerateContentArray

func GenerateContentArray(schema *Schema, valueReplacer ValueReplacer, state *ReplaceState) any

func GenerateContentFromSchema

func GenerateContentFromSchema(schema *Schema, valueResolver ValueReplacer, state *ReplaceState) any

func GenerateContentObject

func GenerateContentObject(schema *Schema, valueReplacer ValueReplacer, state *ReplaceState) any

func GenerateQuery

func GenerateQuery(valueReplacer ValueReplacer, params OpenAPIParameters) string

func GenerateRequestHeaders

func GenerateRequestHeaders(parameters OpenAPIParameters, valueReplacer ValueReplacer) any

func GenerateResponseHeaders

func GenerateResponseHeaders(headers OpenAPIHeaders, valueReplacer ValueReplacer) http.Header

func GenerateURLFromSchemaParameters

func GenerateURLFromSchemaParameters(path string, valueResolver ValueReplacer, params OpenAPIParameters) string

func GetFakeFuncFactoryWithString

func GetFakeFuncFactoryWithString() map[string]FakeFuncFactoryWithString

GetFakeFuncFactoryWithString returns a map of utility fake functions.

func GetFakes

func GetFakes() map[string]FakeFunc

GetFakes returns a map of fake functions from underlying fake library by gathering all exported methods from the faker.Faker struct into map. The keys are the snake_cased dot-separated method names, which reflect the location of the function: For example: person.first_name will return a fake first name from the Person struct.

func GetFileHash

func GetFileHash(file io.Reader) string

func GetJSONPayload

func GetJSONPayload[T any](req *http.Request) (*T, error)

func GetRandomKeyFromMap

func GetRandomKeyFromMap[T any](m map[string]T) string

func GetRandomSliceValue

func GetRandomSliceValue[T any](slice []T) T

GetRandomSliceValue returns a random value from the given slice.

func GetSliceMaxRepetitionNumber

func GetSliceMaxRepetitionNumber[T comparable](values []T) int

GetSliceMaxRepetitionNumber returns the maximum number of non-unique values in the given slice.

func GetSortedMapKeys

func GetSortedMapKeys[T any](content map[string]T) []string

func GetValueByDottedPath

func GetValueByDottedPath(data map[string]any, path string) any

func HandleErrorAndLatency

func HandleErrorAndLatency(svcConfig *ServiceConfig, w http.ResponseWriter) bool

func HasCorrectSchemaValue

func HasCorrectSchemaValue(ctx *ReplaceContext, value any) bool

HasCorrectSchemaValue checks if the value is of the correct type and format.

func IsCorrectlyReplacedType

func IsCorrectlyReplacedType(value any, neededType string) bool

func IsEmptyDir

func IsEmptyDir(path string) bool

IsEmptyDir checks if a directory is empty.

func IsInteger

func IsInteger(value interface{}) bool

func IsJsonType

func IsJsonType(content []byte) bool

IsJsonType checks if the content is a valid JSON document.

func IsMap

func IsMap(i any) bool

func IsNumber

func IsNumber(value interface{}) bool

func IsSliceUnique

func IsSliceUnique[T comparable](path []T) bool

IsSliceUnique returns true if all values in the given slice are unique.

func IsValidHTTPVerb

func IsValidHTTPVerb(verb string) bool

IsValidHTTPVerb checks if the given HTTP verb is valid.

func IsValidURLResource

func IsValidURLResource(urlPattern string) bool

IsValidURLResource checks if the given URL resource pattern is valid: placeholders contain only alphanumeric characters, underscores, and hyphens

func IsYamlType

func IsYamlType(content []byte) bool

IsYamlType checks if the content is a valid YAML document.

func MaybeRegexPattern

func MaybeRegexPattern(input string) bool

MaybeRegexPattern checks if the input string contains any special characters. This is a simple good-enough check to see if the context key is a regex pattern.

func MustFileStructure

func MustFileStructure(paths *Paths) error

MustFileStructure creates the necessary directories and files

func NewDocumentFromFileFactory

func NewDocumentFromFileFactory(provider SchemaProvider) func(filePath string) (Document, error)

func RemovePointer

func RemovePointer[T bool | float64 | int64 | uint64](value *T) T

func ReplaceFromContext

func ReplaceFromContext(ctx *ReplaceContext) any

func ReplaceFromSchemaExample

func ReplaceFromSchemaExample(ctx *ReplaceContext) any

func ReplaceFromSchemaFallback

func ReplaceFromSchemaFallback(ctx *ReplaceContext) any

ReplaceFromSchemaFallback is the last resort to get a value from the schema.

func ReplaceFromSchemaFormat

func ReplaceFromSchemaFormat(ctx *ReplaceContext) any

func ReplaceFromSchemaPrimitive

func ReplaceFromSchemaPrimitive(ctx *ReplaceContext) any

func ReplaceInHeaders

func ReplaceInHeaders(ctx *ReplaceContext) any

func ReplaceInPath

func ReplaceInPath(ctx *ReplaceContext) any

func ReplaceValueWithContext

func ReplaceValueWithContext(path []string, contextData any) interface{}

func SaveFile

func SaveFile(filePath string, data []byte) error

SaveFile saves a file to the specified path. If the destination directory doesn't exist, it will be created.

func SetValueByDottedPath

func SetValueByDottedPath(data map[string]any, path string, value any)

func SliceContains

func SliceContains[T comparable](slice []T, value T) bool

SliceContains returns true if the given slice contains the given value.

func SliceDeleteAtIndex

func SliceDeleteAtIndex[T any](slice []T, index int) []T

SliceDeleteAtIndex deletes an element from a slice at the given index and preserves the order of the slice.

func SliceUnique

func SliceUnique[T comparable](slice []T) []T

SliceUnique returns a new slice with unique values from the given slice.

func ToFloat64

func ToFloat64(value interface{}) (float64, error)

func ToInt32

func ToInt32(value any) (int32, bool)

ToInt32 converts underlying value to int32 if it can be represented as int32

func ToInt64

func ToInt64(value any) (int64, bool)

ToInt64 converts underlying value to int64 if it can be represented as int64

func ToSnakeCase

func ToSnakeCase(input string) string

ToSnakeCase converts a string to snake_case case

func TransformHTTPCode

func TransformHTTPCode(httpCode string) int

func ValidateRequest

func ValidateRequest(req *http.Request, body *Schema, contentType string) error

ValidateRequest validates request against a schema.

func ValidateResponse

func ValidateResponse(req *http.Request, res *Response, operation Operationer) error

ValidateResponse validates a response against an operation. Response must contain non-empty headers or it'll fail validation.

func ValidateStringWithPattern

func ValidateStringWithPattern(input string, pattern string) bool

ValidateStringWithPattern checks if the input string matches the given pattern.

Types

type APIResponse

type APIResponse struct {
	*BaseResponse
}

func NewAPIResponse

func NewAPIResponse(w http.ResponseWriter) *APIResponse

func (*APIResponse) Send

func (r *APIResponse) Send(data []byte)

func (*APIResponse) WithHeader

func (r *APIResponse) WithHeader(key string, value string) *APIResponse

func (*APIResponse) WithStatusCode

func (r *APIResponse) WithStatusCode(code int) *APIResponse

type Any

type Any interface {
	string | int | bool | float64 | any
}

type App

type App struct {
	Router     *Router
	BluePrints []RouteRegister
	Paths      *Paths
	// contains filtered or unexported fields
}

func NewApp

func NewApp(config *Config) *App

func (*App) AddBluePrint

func (a *App) AddBluePrint(bluePrint RouteRegister) error

func (*App) Run

func (a *App) Run()

type AppConfig

type AppConfig struct {
	// Port is the port number to listen on.
	Port int `json:"port" yaml:"port" koanf:"port"`

	// HomeURL is the URL for the UI home page.
	HomeURL string `json:"homeUrl" yaml:"homeURL" koanf:"homeUrl"`

	// ServiceURL is the URL for the service and resources endpoints in the UI.
	ServiceURL string `json:"serviceUrl" yaml:"serviceURL" koanf:"serviceUrl"`

	// SettingsURL is the URL for the settings endpoint in the UI.
	SettingsURL string `json:"settingsUrl" yaml:"settingsURL" koanf:"settingsUrl"`

	// ContextURL is the URL for the context endpoint in the UI.
	ContextURL string `json:"contextUrl" yaml:"contextUrl" koanf:"contextUrl"`

	// ContextAreaPrefix sets sub-contexts for replacements in path, header or any other supported place.
	//
	// for example:
	// in-path:
	//   user_id: "fake.ids.int8"
	ContextAreaPrefix string `json:"contextAreaPrefix" yaml:"contextAreaPrefix" koanf:"contextAreaPrefix"`

	// DisableUI is a flag whether to disable the UI.
	DisableUI bool `json:"disableUI" yaml:"disableUI" koanf:"disableUI"`

	// DisableSpec is a flag whether to disable the Swagger UI.
	DisableSwaggerUI bool `json:"disableSwaggerUI" yaml:"disableSwaggerUI" koanf:"disableSwaggerUI"`

	// SchemaProvider is the schema provider to use: kin-openapi or libopenapi.
	SchemaProvider SchemaProvider `json:"schemaProvider" yaml:"schemaProvider" koanf:"schemaProvider"`

	// Paths is the paths to various resource directories.
	Paths *Paths `json:"-" koanf:"-"`

	// CreateFileStructure is a flag whether to create the initial resources file structure:
	// contexts, services, etc.
	// It will also copy sample files from the samples directory into services.
	// Default: true
	CreateFileStructure bool `koanf:"createFileStructure" json:"createFileStructure" yaml:"createFileStructure"`

	Editor *EditorConfig `koanf:"editor" json:"editor" yaml:"editor"`
}

AppConfig is the app configuration.

func NewDefaultAppConfig

func NewDefaultAppConfig(baseDir string) *AppConfig

func (*AppConfig) IsValidPrefix

func (a *AppConfig) IsValidPrefix(prefix string) bool

IsValidPrefix returns true if the prefix is not a reserved URL.

type BaseHandler

type BaseHandler struct {
}

func (*BaseHandler) JSONResponse

func (h *BaseHandler) JSONResponse(w http.ResponseWriter) *JSONResponse

func (*BaseHandler) Response

func (h *BaseHandler) Response(w http.ResponseWriter) *APIResponse

type BaseOperation

type BaseOperation struct {
}

type BaseResponse

type BaseResponse struct {
	// contains filtered or unexported fields
}

type BoolValue

type BoolValue bool

func (BoolValue) Get

func (b BoolValue) Get() any

type CacheOperationAdapter

type CacheOperationAdapter struct {
	// contains filtered or unexported fields
}

func (*CacheOperationAdapter) GetParameters

func (a *CacheOperationAdapter) GetParameters() OpenAPIParameters

func (*CacheOperationAdapter) GetRequestBody

func (a *CacheOperationAdapter) GetRequestBody() (*Schema, string)

func (*CacheOperationAdapter) GetResponse

func (a *CacheOperationAdapter) GetResponse() *OpenAPIResponse

func (*CacheOperationAdapter) ID

func (a *CacheOperationAdapter) ID() string

func (*CacheOperationAdapter) WithParseConfig

func (a *CacheOperationAdapter) WithParseConfig(parseConfig *ParseConfig) Operationer

type CacheStorage

type CacheStorage interface {
	Set(key string, value any) error
	Get(key string) (any, bool)
}

type Config

type Config struct {
	// App is the app config.
	App *AppConfig `koanf:"app" json:"app" yaml:"app"`

	// Services is a map of service name and the corresponding config.
	// ServiceName is the first part of the path.
	// e.g. /petstore/v1/pets -> petstore
	// in case, there's no service name, the name ".root" will be used.
	Services map[string]*ServiceConfig `koanf:"services" json:"services" yaml:"services"`

	Replacers []Replacer `koanf:"-" json:"-" yaml:"-"`
	// contains filtered or unexported fields
}

func MustConfig

func MustConfig(baseDir string) *Config

MustConfig creates a new config from a YAML file path. In case it file does not exist or has incorrect YAML: - it creates a new default config

Koanf has a file watcher, but its easier to control the changes with a manual reload.

func NewConfigFromContent

func NewConfigFromContent(content []byte) (*Config, error)

NewConfigFromContent creates a new config from a YAML file content.

func NewDefaultConfig

func NewDefaultConfig(baseDir string) *Config

NewDefaultConfig creates a new default config in case the config file is missing, not found or any other error.

func (*Config) EnsureConfigValues

func (c *Config) EnsureConfigValues()

EnsureConfigValues ensures that all config values are set.

func (*Config) GetApp

func (c *Config) GetApp() *AppConfig

func (*Config) GetServiceConfig

func (c *Config) GetServiceConfig(service string) *ServiceConfig

GetServiceConfig returns the config for a service. If the service is not found, it returns a default config.

func (*Config) Reload

func (c *Config) Reload()

type ContentExample

type ContentExample struct {
	CURL string `json:"curl,omitempty"`
}

type ContextHandler

type ContextHandler struct {
	*BaseHandler
	// contains filtered or unexported fields
}

type ContextListResponse

type ContextListResponse struct {
	Items []string `json:"items"`
}

type Document

type Document interface {
	Provider() SchemaProvider
	GetVersion() string
	GetResources() map[string][]string
	FindOperation(options *OperationDescription) Operationer
}

func NewKinDocumentFromFile

func NewKinDocumentFromFile(filePath string) (Document, error)

func NewLibOpenAPIDocumentFromFile

func NewLibOpenAPIDocumentFromFile(filePath string) (Document, error)

type EditorConfig

type EditorConfig struct {
	Theme    string `koanf:"theme" json:"theme" yaml:"theme"`
	FontSize int    `koanf:"fontSize" json:"fontSize" yaml:"fontSize"`
}

type ErrorMessage

type ErrorMessage struct {
	Message string `json:"message"`
}

func NewErrorMessage

func NewErrorMessage(err error) *ErrorMessage

type ErrorResponse

type ErrorResponse struct {
	Error   string          `json:"error"`
	Details []*ErrorMessage `json:"details"`
}

type FakeFunc

type FakeFunc func() MixedValue

type FakeFuncFactoryWithString

type FakeFuncFactoryWithString func(value string) FakeFunc

type FakeValue

type FakeValue interface {
	~string | ~int | ~float64 | ~bool
}

type FileProperties

type FileProperties struct {
	// ServiceName is the name of the service that the file belongs to.
	// It represents the first directory in the file path.
	ServiceName string

	// IsOpenAPI indicates whether the file is an OpenAPI specification.
	IsOpenAPI bool

	// Method is the HTTP method of the resource, which this file describes.
	Method string

	// Prefix is the path prefix of the resource, which this file describes.
	// This is service name with a leading slash.
	Prefix string

	// Resource is the path of the resource, which this file describes without prefix.
	Resource string

	// FilePath is the full path to the file.
	FilePath string

	// FileName is the name of the file with the extension.
	FileName string

	// Extension is the extension of the file, with the leading dot.
	Extension string

	// ContentType is the MIME type of the file.
	ContentType string

	// Spec is the OpenAPI specification of the file if the file iis an OpenAPI specification.
	Spec Document `json:"-"`
}

FileProperties contains inferred properties of a file that is being loaded from service directory.

func GetPropertiesFromFilePath

func GetPropertiesFromFilePath(filePath string, appCfg *AppConfig) (*FileProperties, error)

GetPropertiesFromFilePath gets properties of a file from its path.

func (*FileProperties) IsEqual

func (f *FileProperties) IsEqual(other *FileProperties) bool

IsEqual compares two FileProperties structs. Spec is not compared.

type Float64Value

type Float64Value float64

func (Float64Value) Get

func (f Float64Value) Get() any

type GenerateResponse

type GenerateResponse struct {
	Request  *Request  `json:"request"`
	Response *Response `json:"response"`
}

type HomeHandler

type HomeHandler struct {
	*BaseHandler
	// contains filtered or unexported fields
}

type IntValue

type IntValue int

func (IntValue) Get

func (i IntValue) Get() any

type JSONResponse

type JSONResponse struct {
	*BaseResponse
}

func NewJSONResponse

func NewJSONResponse(w http.ResponseWriter) *JSONResponse

func (*JSONResponse) Send

func (r *JSONResponse) Send(data any)

Send sends the data as JSON to the client. WriteHeader must be called before any writing happens and just once.

func (*JSONResponse) WithHeader

func (r *JSONResponse) WithHeader(key string, value string) *JSONResponse

func (*JSONResponse) WithStatusCode

func (r *JSONResponse) WithStatusCode(code int) *JSONResponse

type KinDocument

type KinDocument struct {
	*openapi3.T
}

func (*KinDocument) FindOperation

func (d *KinDocument) FindOperation(options *OperationDescription) Operationer

func (*KinDocument) GetResources

func (d *KinDocument) GetResources() map[string][]string

func (*KinDocument) GetVersion

func (d *KinDocument) GetVersion() string

func (*KinDocument) Provider

func (d *KinDocument) Provider() SchemaProvider

type KinOperation

type KinOperation struct {
	*openapi3.Operation
	// contains filtered or unexported fields
}

func (*KinOperation) GetParameters

func (op *KinOperation) GetParameters() OpenAPIParameters

func (*KinOperation) GetRequestBody

func (op *KinOperation) GetRequestBody() (*Schema, string)

func (*KinOperation) GetResponse

func (op *KinOperation) GetResponse() *OpenAPIResponse

func (*KinOperation) ID

func (op *KinOperation) ID() string

func (*KinOperation) WithParseConfig

func (op *KinOperation) WithParseConfig(config *ParseConfig) Operationer

type LibV2Document

type LibV2Document struct {
	*libopenapi.DocumentModel[v2high.Swagger]
	ParseConfig *ParseConfig
}

func (*LibV2Document) FindOperation

func (d *LibV2Document) FindOperation(options *OperationDescription) Operationer

func (*LibV2Document) GetResources

func (d *LibV2Document) GetResources() map[string][]string

func (*LibV2Document) GetVersion

func (d *LibV2Document) GetVersion() string

func (*LibV2Document) Provider

func (d *LibV2Document) Provider() SchemaProvider

type LibV2Operation

type LibV2Operation struct {
	*v2high.Operation
	ParseConfig *ParseConfig
	// contains filtered or unexported fields
}

func (*LibV2Operation) GetParameters

func (op *LibV2Operation) GetParameters() OpenAPIParameters

func (*LibV2Operation) GetRequestBody

func (op *LibV2Operation) GetRequestBody() (*Schema, string)

func (*LibV2Operation) GetResponse

func (op *LibV2Operation) GetResponse() *OpenAPIResponse

func (*LibV2Operation) ID

func (op *LibV2Operation) ID() string

func (*LibV2Operation) WithParseConfig

func (op *LibV2Operation) WithParseConfig(parseConfig *ParseConfig) Operationer

type LibV3Document

type LibV3Document struct {
	*libopenapi.DocumentModel[v3high.Document]
}

func (*LibV3Document) FindOperation

func (d *LibV3Document) FindOperation(options *OperationDescription) Operationer

func (*LibV3Document) GetResources

func (d *LibV3Document) GetResources() map[string][]string

func (*LibV3Document) GetVersion

func (d *LibV3Document) GetVersion() string

func (*LibV3Document) Provider

func (d *LibV3Document) Provider() SchemaProvider

type LibV3Operation

type LibV3Operation struct {
	*v3high.Operation
	// contains filtered or unexported fields
}

func (*LibV3Operation) GetParameters

func (op *LibV3Operation) GetParameters() OpenAPIParameters

func (*LibV3Operation) GetRequestBody

func (op *LibV3Operation) GetRequestBody() (*Schema, string)

func (*LibV3Operation) GetResponse

func (op *LibV3Operation) GetResponse() *OpenAPIResponse

func (*LibV3Operation) ID

func (op *LibV3Operation) ID() string

func (*LibV3Operation) WithParseConfig

func (op *LibV3Operation) WithParseConfig(parseConfig *ParseConfig) Operationer

type MemoryStorage

type MemoryStorage struct {
	// contains filtered or unexported fields
}

func NewMemoryStorage

func NewMemoryStorage() *MemoryStorage

func (*MemoryStorage) Get

func (s *MemoryStorage) Get(key string) (any, bool)

func (*MemoryStorage) Set

func (s *MemoryStorage) Set(key string, value any) error

type MixedValue

type MixedValue interface {
	Get() any
}

type OpenAPIHandler

type OpenAPIHandler struct {
	*BaseHandler
	// contains filtered or unexported fields
}

type OpenAPIHeaders

type OpenAPIHeaders map[string]*OpenAPIParameter

type OpenAPIParameter

type OpenAPIParameter struct {
	Name     string      `json:"name,omitempty" yaml:"name,omitempty"`
	In       string      `json:"in,omitempty" yaml:"in,omitempty"`
	Required bool        `json:"required,omitempty" yaml:"required,omitempty"`
	Schema   *Schema     `json:"schema,omitempty" yaml:"schema,omitempty"`
	Example  interface{} `json:"example,omitempty" yaml:"example,omitempty"`
}

type OpenAPIParameters

type OpenAPIParameters []*OpenAPIParameter

type OpenAPIResponse

type OpenAPIResponse struct {
	Headers     OpenAPIHeaders
	Content     *Schema
	ContentType string
	StatusCode  int
}

type OperationDescription

type OperationDescription struct {
	Service  string
	Resource string
	Method   string
}

type Operationer

type Operationer interface {
	ID() string
	GetParameters() OpenAPIParameters
	GetRequestBody() (*Schema, string)
	GetResponse() *OpenAPIResponse
	WithParseConfig(*ParseConfig) Operationer
}

func NewCacheOperationAdapter

func NewCacheOperationAdapter(service string, operation Operationer, storage CacheStorage) Operationer

type ParseConfig

type ParseConfig struct {
	// MaxLevels is the maximum level to parse.
	MaxLevels int `koanf:"maxLevels" json:"maxLevels" yaml:"maxLevels"`

	// MaxRecursionLevels is the maximum level to parse recursively.
	// 0 means no recursion: property will get nil value.
	MaxRecursionLevels int `koanf:"maxRecursionLevels" json:"maxRecursionLevels" yaml:"maxRecursionLevels"`

	// OnlyRequired is a flag whether to include only required fields.
	// If the spec contains deep references, this might significantly speed up parsing.
	OnlyRequired bool `koanf:"onlyRequired" json:"onlyRequired" yaml:"onlyRequired"`
}

type ParsedContextResult

type ParsedContextResult struct {
	Result  map[string]any
	Aliases map[string]string
}

func ParseContextFile

func ParseContextFile(filePath string) (*ParsedContextResult, error)

ParseContextFile parses a YAML file and returns a map of context properties. Filename without extension is used as the context namespace and can be referenced: - in service config - when creating aliases

func ParseContextFromBytes

func ParseContextFromBytes(content []byte) (*ParsedContextResult, error)

type Paths

type Paths struct {
	Base              string
	Resources         string
	Data              string
	Contexts          string
	Docs              string
	Samples           string
	Services          string
	ServicesOpenAPI   string
	ServicesFixedRoot string
	UI                string
	ConfigFile        string
}

func NewPaths

func NewPaths(baseDir string) *Paths

type ReplaceContext

type ReplaceContext struct {
	Schema     any
	State      *ReplaceState
	AreaPrefix string
	Data       []map[string]any
	Faker      faker.Faker
}

type ReplaceState

type ReplaceState struct {
	NamePath     []string
	ElementIndex int
	IsHeader     bool
	IsPathParam  bool
	ContentType  string
	// contains filtered or unexported fields
}

func (*ReplaceState) NewFrom

func (s *ReplaceState) NewFrom(src *ReplaceState) *ReplaceState

func (*ReplaceState) WithContentType

func (s *ReplaceState) WithContentType(value string) *ReplaceState

func (*ReplaceState) WithElementIndex

func (s *ReplaceState) WithElementIndex(value int) *ReplaceState

func (*ReplaceState) WithHeader

func (s *ReplaceState) WithHeader() *ReplaceState

func (*ReplaceState) WithName

func (s *ReplaceState) WithName(name string) *ReplaceState

func (*ReplaceState) WithPathParam

func (s *ReplaceState) WithPathParam() *ReplaceState

type Replacer

type Replacer func(ctx *ReplaceContext) any

type Request

type Request struct {
	Headers     any             `json:"headers,omitempty"`
	Method      string          `json:"method,omitempty"`
	Path        string          `json:"path,omitempty"`
	Query       any             `json:"query,omitempty"`
	Body        string          `json:"body,omitempty"`
	ContentType string          `json:"contentType,omitempty"`
	Examples    *ContentExample `json:"examples,omitempty"`
}

func NewRequestFromOperation

func NewRequestFromOperation(pathPrefix, path, method string, operation Operationer, valueReplacer ValueReplacer) *Request

NewRequestFromOperation creates a new request from an operation. It used to pre-generate payloads from the UI or provide service to generate such. It's not part of OpenAPI endpoint handler.

type ResourceGeneratePayload

type ResourceGeneratePayload struct {
	Replacements map[string]any `json:"replacements"`
}

type ResourceResponse

type ResourceResponse struct {
	Method      string `json:"method"`
	Path        string `json:"path"`
	Extension   string `json:"extension"`
	ContentType string `json:"contentType"`
	Content     string `json:"content"`
}

type Response

type Response struct {
	Headers     http.Header `json:"headers,omitempty"`
	Content     []byte      `json:"content,omitempty"`
	ContentType string      `json:"contentType,omitempty"`
	StatusCode  int         `json:"statusCode,omitempty"`
}

func NewResponseFromOperation

func NewResponseFromOperation(operation Operationer, valueReplacer ValueReplacer) *Response

type RouteDescription

type RouteDescription struct {
	Method      string          `json:"method"`
	Path        string          `json:"path"`
	Type        string          `json:"type"`
	ContentType string          `json:"contentType"`
	Overwrites  bool            `json:"overwrites"`
	File        *FileProperties `json:"-"`
}

RouteDescription describes a route for the UI Application. Path is relative to the service prefix.

type RouteDescriptions

type RouteDescriptions []*RouteDescription

func (RouteDescriptions) Sort

func (rs RouteDescriptions) Sort()

Sort sorts the routes by path and method. The order is: GET, POST, other methods (alphabetically)

type RouteRegister

type RouteRegister func(router *Router) error

type Router

type Router struct {
	*chi.Mux
	Services     map[string]*ServiceItem
	Config       *Config
	Contexts     map[string]map[string]any
	ContextNames []map[string]string
	// contains filtered or unexported fields
}

func NewRouter

func NewRouter(config *Config) *Router

func (*Router) RemoveContext

func (r *Router) RemoveContext(name string)

type SavedResourceResponse

type SavedResourceResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
	ID      int    `json:"id"`
}

type Schema

type Schema struct {
	Type string `json:"type,omitempty" yaml:"type,omitempty"`

	// in 3.1 examples can be an array (which is recommended)
	Examples []any `json:"examples,omitempty" yaml:"examples,omitempty"`

	// items can be a schema in 2.0, 3.0 and 3.1 or a bool in 3.1
	Items *Schema `json:"items,omitempty" yaml:"items,omitempty"`

	// Compatible with all versions
	MultipleOf    float64            `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
	Maximum       float64            `json:"maximum,omitempty" yaml:"maximum,omitempty"`
	Minimum       float64            `json:"minimum,omitempty" yaml:"minimum,omitempty"`
	MaxLength     int64              `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
	MinLength     int64              `json:"minLength,omitempty" yaml:"minLength,omitempty"`
	Pattern       string             `json:"pattern,omitempty" yaml:"pattern,omitempty"`
	Format        string             `json:"format,omitempty" yaml:"format,omitempty"`
	MaxItems      int64              `json:"maxItems,omitempty" yaml:"maxItems,omitempty"`
	MinItems      int64              `json:"minItems,omitempty" yaml:"minItems,omitempty"`
	MaxProperties int64              `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
	MinProperties int64              `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
	Required      []string           `json:"required,omitempty" yaml:"required,omitempty"`
	Enum          []any              `json:"enum,omitempty" yaml:"enum,omitempty"`
	Properties    map[string]*Schema `json:"properties,omitempty" yaml:"properties,omitempty"`
	Not           *Schema            `json:"not,omitempty" yaml:"not,omitempty"`
	Default       any                `json:"default,omitempty" yaml:"default,omitempty"`
	Nullable      bool               `json:"nullable,omitempty" yaml:"nullable,omitempty"`
	ReadOnly      bool               `json:"readOnly,omitempty" yaml:"readOnly,omitempty"`
	WriteOnly     bool               `json:"writeOnly,omitempty" yaml:"writeOnly,omitempty"`
	Example       any                `json:"example,omitempty" yaml:"example,omitempty"`
	Deprecated    bool               `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
}

func NewSchemaFromKin

func NewSchemaFromKin(schema *openapi3.Schema, parseConfig *ParseConfig) *Schema

func NewSchemaFromLibOpenAPI

func NewSchemaFromLibOpenAPI(schema *base.Schema, parseConfig *ParseConfig) *Schema

type SchemaProvider

type SchemaProvider string
const (
	KinOpenAPIProvider    SchemaProvider = "kin-openapi"
	LibOpenAPIProvider    SchemaProvider = "libopenapi"
	DefaultSchemaProvider SchemaProvider = LibOpenAPIProvider
)

type SchemaWithContentType

type SchemaWithContentType struct {
	Schema      *Schema
	ContentType string
}

type ServiceCacheConfig

type ServiceCacheConfig struct {
	// Avoid multiple schema parsing by caching the parsed schema.
	// Default: true
	Schema bool `koanf:"schema" json:"schema" yaml:"schema"`
}

type ServiceConfig

type ServiceConfig struct {
	// Latency is the latency to add to the response.
	// Latency not used in the services API, only when endpoint queried directly.
	Latency time.Duration `koanf:"latency" json:"latency" yaml:"latency"`

	// Errors is the error config.
	Errors *ServiceError `koanf:"errors" json:"errors" yaml:"errors"`

	// Contexts is the list of contexts to use for replacements.
	// It is a map of context name defined either in the UI or filename without extension.
	// You can refer to the name when building aliases.
	Contexts []map[string]string `koanf:"contexts" json:"contexts" yaml:"contexts"`

	// ParseConfig is the config for parsing the OpenAPI spec.
	ParseConfig *ParseConfig `json:"parseConfig" yaml:"parseConfig" koanf:"parseConfig"`

	// Validate is the validation config.
	// It is used to validate the request and/or response outside of the Services API.
	Validate *ServiceValidateConfig `koanf:"validate" json:"validate" yaml:"validate"`

	// Cache is the cache config.
	Cache *ServiceCacheConfig `koanf:"cache" json:"cache" yaml:"cache"`
}

type ServiceDescription

type ServiceDescription struct {
	Name      string
	Method    string
	Path      string
	Ext       string
	IsOpenAPI bool
}

type ServiceEmbedded

type ServiceEmbedded struct {
	Name string `json:"name"`
}

type ServiceError

type ServiceError struct {
	// Chance is the chance to return an error.
	// In the config, it can be set with %-suffix.
	Chance int `koanf:"chance" json:"chance" yaml:"chance"`

	// Codes is a map of error codes and their weights if Chance > 0.
	// If no error codes are specified, it returns a 500 error code.
	Codes map[int]int `koanf:"codes" json:"codes" yaml:"codes"`
	// contains filtered or unexported fields
}

func (*ServiceError) GetError

func (s *ServiceError) GetError() int

GetError returns an error code based on the chance and error weights. If no error weights are specified, it returns a 500 error code. If the chance is 0, it returns 0.

type ServiceHandler

type ServiceHandler struct {
	*BaseHandler
	// contains filtered or unexported fields
}

type ServiceItem

type ServiceItem struct {
	Name         string            `json:"name"`
	Routes       RouteDescriptions `json:"routes"`
	OpenAPIFiles []*FileProperties `json:"-"`
	// contains filtered or unexported fields
}

func (*ServiceItem) AddOpenAPIFile

func (i *ServiceItem) AddOpenAPIFile(file *FileProperties)

func (*ServiceItem) AddRoutes

func (i *ServiceItem) AddRoutes(routes RouteDescriptions)

AddRoutes adds routes to the service. There's no check for duplicates.

type ServiceItemResponse

type ServiceItemResponse struct {
	Name             string   `json:"name"`
	OpenAPIResources []string `json:"openApiResources"`
}

type ServiceListResponse

type ServiceListResponse struct {
	Items []*ServiceItemResponse `json:"items"`
}

type ServicePayload

type ServicePayload struct {
	Name        string        `json:"name"`
	IsOpenAPI   bool          `json:"isOpenApi"`
	Method      string        `json:"method"`
	Path        string        `json:"path"`
	Response    []byte        `json:"response"`
	ContentType string        `json:"contentType"`
	File        *UploadedFile `json:"file"`
}

type ServiceResourcesResponse

type ServiceResourcesResponse struct {
	Service          *ServiceEmbedded  `json:"service"`
	Endpoints        RouteDescriptions `json:"endpoints"`
	OpenAPISpecNames []string          `json:"openapiSpecNames"`
}

type ServiceValidateConfig

type ServiceValidateConfig struct {
	// Request is a flag whether to validate the request.
	// Default: true
	Request bool `koanf:"request" json:"request" yaml:"request"`

	// Response is a flag whether to validate the response.
	// Default: false
	Response bool `koanf:"response" json:"response" yaml:"response"`
}

type SettingsHandler

type SettingsHandler struct {
	*BaseHandler
	// contains filtered or unexported fields
}

type SimpleResponse

type SimpleResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
}

type StringValue

type StringValue string

func (StringValue) Get

func (s StringValue) Get() any

type UploadedFile

type UploadedFile struct {
	// Content is the content of the file.
	Content []byte

	// Filename is the name of the file.
	Filename string

	// Extension is the extension of the file with the leading dot.
	Extension string

	// Size is the size of the file in bytes.
	Size int64
}

UploadedFile represents an uploaded file.

func GetRequestFile

func GetRequestFile(r *http.Request, fieldName string) (*UploadedFile, error)

GetRequestFile gets an uploaded file from a request.

type ValueReplacer

type ValueReplacer func(schemaOrContent any, state *ReplaceState) any

func CreateValueReplacer

func CreateValueReplacer(cfg *Config, contexts []map[string]any) ValueReplacer

Jump to

Keyboard shortcuts

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