pb33f / wiretap Goto Github PK
View Code? Open in Web Editor NEWThe world's coolest API Validation and compliance tool. Validate APIs against OpenAPI specifications and much more
Home Page: https://pb33f.io/wiretap/
License: Other
The world's coolest API Validation and compliance tool. Validate APIs against OpenAPI specifications and much more
Home Page: https://pb33f.io/wiretap/
License: Other
While running mock server with command yarn wiretap -s ./swagger.yml -u http://localhost:3000 -x
I have incosistent behaviour of path parameter validator.
I have this parameter defined in OpenApi yaml file:
PathTrackId:
in: path
name: trackId
required: true
schema:
type: string
pattern: ^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
example: 123e4567-e89b-12d3-a456-426614174000
format: uuid
minLength: 32
maxLength: 36
and it is used in a path like this:
/contents/tracks/{trackId}:
get:
tags:
- Contents
summary: Get tracks based on {trackId}, from contents
operationId: contentsTracksTrackIdGet
parameters:
- $ref: '#/components/parameters/PathTrackId'
My frontend app sends request with some example ID:
GET http://localhost:4200/api/contents/tracks/123e4567-e89b-12d3-a456-426614174010
where http://localhost:4200/api/
is a proxy for default wiretap http://localhost:9000
.
Wiretap returns
{
"type": "https://pb33f.io/wiretap/error",
"title": "unable to serve mocked response",
"status": 500,
"detail": "Error: Path parameter 'trackId' failed to validate, Reason: The path parameter 'trackId' is defined as an string, however it failed to pass a schema validation, Validation Errors: [Reason: 'tracks' is not valid 'uuid', Location: /format Reason: length must be \u003e= 32, but got 6, Location: /minLength Reason: does not match pattern '^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$', Location: /pattern], Line: 47, Column: 9"
}
when request is send for the first time but its ok if the same request is send once again.
First request - 500:
GET /api/contents/tracks/123e4567-e89b-12d3-a456-426614174010 HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Authorization: test_token
Connection: keep-alive
DNT: 1
Host: localhost:4200
Referer: http://localhost:4200/app/game/track/123e4567-e89b-12d3-a456-426614174010
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
sec-ch-ua: "Not-A.Brand";v="99", "Chromium";v="124"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Second request - OK:
GET /api/contents/tracks/123e4567-e89b-12d3-a456-426614174010 HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Authorization: test_token
Connection: keep-alive
DNT: 1
Host: localhost:4200
Referer: http://localhost:4200/app/game/track/123e4567-e89b-12d3-a456-426614174010
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
sec-ch-ua: "Not-A.Brand";v="99", "Chromium";v="124"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Hi, awesome tool. I'd love to use it at work for my development team, however, the AGPL license forces any system that connects to it to be open sourced. That forces proprietary business services, both internal and external, to be open sourced. As such it's not useable. Would you consider using a BSL license or similar, which prohibits anyone for making money by providing the software as a service while still enabling internal use cases for businesses. Thanks for your consideration.
consider this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/anything/pathParams/json/{jsonObj}:
get:
x-speakeasy-test: true
operationId: pathParameterJson
tags:
- parameters
parameters:
- name: jsonObj
in: path
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/simpleObject"
responses:
"200":
content:
application/json:
schema:
title: res
type: object
properties:
url:
type: string
example: 'http://localhost:35123/anything/pathParams/json/{"any":"any","bigint":8821239038968084,"bigintStr":"9223372036854775808","bool":true,"boolOpt":true,"date":"2020-01-01","dateTime":"2020-01-01T00:00:00.000001Z","decimal":3.141592653589793,"decimalStr":"3.14159265358979344719667586","enum":"one","float32":1.1,"int":1,"int32":1,"int32Enum":55,"intEnum":2,"num":1.1,"str":"test","strOpt":"testOptional"}'
required:
- url
description: OK
components:
schemas:
simpleObject:
description: "A simple object that uses all our supported primitive types and enums and has optional properties."
externalDocs:
description: "A link to the external docs."
url: "https://docs.speakeasyapi.dev"
type: object
properties:
str:
type: string
description: "A string property."
example: "test"
bool:
type: boolean
description: "A boolean property."
example: true
int:
type: integer
description: "An integer property."
example: 1
int32:
type: integer
format: int32
description: "An int32 property."
example: 1
num:
type: number
description: "A number property."
example: 1.1
float32:
type: number
format: float
description: "A float32 property."
example: 1.1
enum:
$ref: "#/components/schemas/enum"
date:
type: string
format: date
description: "A date property."
example: "2020-01-01"
dateTime:
type: string
format: date-time
description: "A date-time property."
example: "2020-01-01T00:00:00.000001Z"
any:
description: "An any property."
example: "any"
strOpt:
type: string
description: "An optional string property."
example: "testOptional"
boolOpt:
type: boolean
description: "An optional boolean property."
example: true
intOptNull:
type: integer
description: "An optional integer property will be null for tests."
numOptNull:
type: number
description: "An optional number property will be null for tests."
intEnum:
type: integer
description: "An integer enum property."
enum:
- 1
- 2
- 3
example: 2
x-speakeasy-enums:
- First
- Second
- Third
int32Enum:
type: integer
format: int32
description: "An int32 enum property."
enum:
- 55
- 69
- 181
example: 55
bigint:
type: integer
format: bigint
example: 8821239038968084
bigintStr:
type: string
format: bigint
example: "9223372036854775808"
decimal:
type: number
format: decimal
example: 3.141592653589793
decimalStr:
type: string
format: decimal
example: "3.14159265358979344719667586"
required:
- str
- bool
- int
- int32
- num
- float32
- enum
- date
- dateTime
- any
- intEnum
- int32Enum
enum:
type: string
description: "A string based enum"
enum:
- "one"
- "two"
- "three"
- "four_and_more"
example: "one"
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
it causes this panic in libopenapi when a request is sent:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0xabcfb7]
goroutine 359 [running]:
github.com/pb33f/libopenapi/datamodel/high/base.(*SchemaProxy).Schema(0x0)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/datamodel/high/base/schema_proxy.go:79 +0x17
github.com/pb33f/libopenapi-validator/parameters.(*paramValidator).ValidatePathParams(0x0?, 0xc00024e000)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/parameters/path_parameters.go:91 +0x452
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest.func1.2(0x0?, 0x0?, 0x0?)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:225 +0x27
created by github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest.func1 in goroutine 356
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:233 +0x3b2
consider the below schemas:
map:
type: object
additionalProperties:
$ref: "#/components/schemas/simpleObject"
example: { "key": "...", "key2": "..." }
arr:
type: array
items:
$ref: "#/components/schemas/simpleObject"
example: ["...", "..."]
These use an example expansion directive of "..."
(btw this is a special directive value speakeasy uses to direct our generator how to generate examples, we would be open to discussing alternative directives that both speakeasy and wiretap could use if you didn't want to support this one) which tells our generator to expand the example with an example value generated from the child schema, ie the additionalProperties
schema or items
schema.
In the examples above we are saying we want the map
example to contain two keys (key
and key2
) where the values are using the example generated from the simpleObject
component. This provides a shorthand to avoid having to define the whole json object in the example at this level and instead take advantage of the fact the examples have already been defined in the component.
The array version is just saying I want two
values of the example defined in the simpleObject
component.
Would love if the mocking from wiretap also supported this (or something similar that we can converge on) as it does reduce the burden for the example implementor.
Given an API specification that defines /ranch
given an backend running on mymachine with a basepath , so responding on
http://mymachine/aBasePath/ThatcanbeseveralsSegments/ranch
it would be nice that
given the wiretab command line :
wiretap -s .\mySpec.yml -u http://mymachine/aBasePath/ThatcanbeseveralsSegments/
that it runs auto magically , ie that when a call is comming on http://wiretapProxy/ranch it goes directed to http://mymachine/aBasePath/ThatcanbeseveralsSegments/ranch without doing more settings
do you think it would be possible to kind of lock down the spec
Kind of setting aditionnal Properties to false with a flag in wiretab command line
meanning given the spec
"schema" : {
"type" : "object",
"properties" : {
"message" : {"type" : "string"},
"who" : {"type" : "string"}
}
if i send "message" : "Hello" , "who":"bob" , "offender":12 , Flag Off = it says green , FlagOn = it says red
the topic beeing to spot that the server returns undocumented fields ...
Line Number | JSON Path | Issue Description |
---|---|---|
150 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/BookingDateTime/format | '2024-01-15T18:45:14' is not valid 'date-time' |
155 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/ValueDateTime/format | '2024-01-15T18:45:14' is not valid 'date-time' |
49 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/TransactionDateTime/format | '2024-01-15T18:45:14' is not valid 'date-time' |
72 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/TransactionType/enum | value must be one of "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx" |
49 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/TransactionDateTime/format | '2024-01-11T15:39:37' is not valid 'date-time' |
72 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/TransactionType/enum | value must be one of "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx", "xxxxxxxx" |
155 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/ValueDateTime/format | '2024-01-11T15:39:37' is not valid 'date-time' |
150 | /xxxx/xxxx/xxxxx/xxxxxx/items/properties/BookingDateTime/format | '2024-01-11T15:39:37' is not valid 'date-time' |
The issue is the line numbers getting printed are incorrect in wiretap UI if the data schema repeats internally representing multiple data set for example transactions
If possible require a immediate fix on the same. Thanks in advance!!
i followed the examples and did
$ curl -o giftshop-openapi.yaml https://api.pb33f.io/wiretap/giftshop-openapi.yaml
$ docker run -p 9090:9090 -p 9091:9091 -p 9092:9092 --rm -v $PWD:/work:rw pb33f/wiretap -u https://api.pb33f.io -s gi
ftshop-openapi.yaml
@@@@@@@ @@@@@@@ @@@@@@ @@@@@@ @@@@@@@@
@@@@@@@@ @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@
@@! @@@ @@! @@@ @@@ @@@ @@!
!@! @!@ !@ @!@ @!@ @!@ !@!
@!@@!@! @!@!@!@ @!@!!@ @!@!!@ @!!!:!
!!@!!! !!!@!!!! !!@!@! !!@!@! !!!!!:
!!: !!: !!! !!: !!: !!:
:!: :!: !:! :!: :!: :!:
:: :: :::: :: :::: :: :::: ::
: :: : :: : : : : : : :
wiretap version: latest | compiled: Fri, 15 Dec 2023 09:30:40 UTC
Designed and built by Princess Beef Heavy Industries: https://pb33f.io/wiretap
INFO No wiretap configuration located. Using defaults
INFO OpenAPI Specification: 'giftshop-openapi.yaml' parsed and read
INFO API Gateway UI booting on port 9090...
INFO Monitor UI booting on port 9091...
โโ wiretap is online! โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| |
| โโ API Gateway โโโโโโโโโโ โโ Monitor UI โโโโโโโโโโโ |
| | http://localhost:9090 | | http://localhost:9091 | |
| โโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโ |
| |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
INFO wiretap is proxying all traffic to 'https://api.pb33f.io'
Then i do
$ curl "http://localhost:9090/wiretap/giftshop/products"
[{"id":"d91a1cc2-ec4e-468a-97dc-7a0325017f1b","shortCode":"pb0001","name":"pb33f t-shirt","description":"A t-shirt with the pb33f logo on the front","price":19.99,"category":"clothes","image":"https://pb33f.io/images/t-shirt.png"},{"id":"3f6713b8-0e05-4724-9553-5f571248a47a","shortCode":"pb0002","name":"pb33f baseball cap","description":"A baseball cap with the pb33f logo on the front","price":29.99,"category":"clothes","image":"https://pb33f.io/images/cap.png"},{"id":"1d4517a3-c099-4a39-a057-b44a66ba6940","shortCode":"pb0003","name":"pb33f coffee cup","description":"A black coffee cup with the pb33f logo on the front and the word 'hack code' on the back","price":15.75,"category":"cups","image":"https://pb33f.io/images/cup.png"},{"id":"457acf29-a43a-413b-908e-017ab048ad19","shortCode":"pb0004","name":"pb33f hoodie","description":"A nice black hoodie with the pb33f logo on the back and 'hack code' on the front","price":39.99,"category":"clothes","image":"https://pb33f.io/images/hoodie.png"},{"id":"91a99caa-8a8b-4176-8f8a-03bb86d1160e","shortCode":"pb0005","name":"pb33f thermos","description":"A black thermos mug with the words 'hack code' written on the front","price":25.99,"category":"cups","image":"https://pb33f.io/images/thermos.png"},{"id":"1c9b473b-b4f0-4b00-8378-f2f99052feb1","shortCode":"pb0006","name":"pb33f shot glass","description":"A solid black shot glass with the words 'hack code' written on the front","price":5.99,"category":"cups","image":"https://pb33f.io/images/shot-glass.png"}]
when i then go to http://localhost:9091 it shows 100% Complinance, 0 Requests and 0 Results
This spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/anything/queryParams/deepObject/obj:
get:
operationId: deepObjectQueryParamsObject
parameters:
- name: objParam
in: query
style: deepObject
schema:
$ref: "components.yaml#/components/schemas/simpleObject"
required: true
- name: objArrParam
in: query
style: deepObject
schema:
type: object
properties:
arr:
type: array
items:
type: string
examples:
- test
- test2
responses:
"200":
description: OK
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
when a request is sent causes the below panic:
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x68 pc=0xade1e6]
goroutine 264 [running]:
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validateValue.func1()
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:178 +0xa9
panic({0xce4100?, 0x1dbe3b0?})
/opt/hostedtoolcache/go/1.21.5/x64/src/runtime/panic.go:914 +0x21f
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validate(0x0, {0x0, 0x0, 0x0}, 0x0, {0x0, 0x0}, {0xcd4cc0, 0xc00034d350?}, {0x0, ...})
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:253 +0x526
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validateValue(0x0, {0xcd4cc0?, 0xc00034d350?}, {0x0, 0x0})
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:182 +0xbf
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).Validate(...)
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:168
github.com/pb33f/libopenapi-validator/parameters.ValidateParameterSchema(0xc0002eaf00, {0xcd4cc0, 0xc00034d350?}, {0xc00095008c, 0x13}, {0xe6ec8a, 0xf}, {0xe718d6, 0x13}, {0xc0005fae78, ...}, ...)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/parameters/validate_parameter.go:84 +0x4c5
github.com/pb33f/libopenapi-validator/parameters.(*paramValidator).ValidateQueryParams(0xc0005e0a40, 0xc00094e000)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/parameters/query_parameters.go:188 +0x1659
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest.func1.2(0x0?, 0x0?, 0x0?)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:225 +0x27
created by github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest.func1 in goroutine 258
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:233 +0x3b2
given a wrong config files
variables:
someVar: localhost:8000
redirectURL: http://localhost:8000
contract: ./component-descriptor.yml
paths:
/*:
target: ${http://localhost:8000}/ranch <= yes i know it is wrong ๐
call then crash with not clear details cf stack below
config miss configuration could be spot at loading time ; or if not possible just catch the null value
::1 - - [06/Oct/2023:11:03:53 +0200] "GET /ranch HTTP/1.1" 200 0 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.47"
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x8 pc=0x5d6b94]
goroutine 573 [running]:
net/url.(*URL).String(0x0)
/opt/hostedtoolcache/go/1.21.0/x64/src/net/url/url.go:810 +0x34
github.com/pb33f/wiretap/daemon.BuildHttpTransaction({0xc00008ec00?, 0xc00008ee00?, 0xc000806ff0?, 0xc000070ea0?}) /home/runner/work/wiretap/wiretap/daemon/build_request.go:140 +0x82f
github.com/pb33f/wiretap/daemon.(*WiretapService).validateRequest(0xc0005f7540, 0xc0009a00c0, 0xc000b82020?)
/home/runner/work/wiretap/wiretap/daemon/validate.go:74 +0x278
created by github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest in goroutine 633
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:157 +0xa65
The Panic was:
`panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x68 pc=0xa4db8a]
goroutine 3406 [running]:github.com/pb33f/libopenapi-validator/requests.(requestBodyValidator).ValidateRequestBody(0xc00878e900, 0xc003411700)
/go/pkg/mod/github.com/pb33f/[email protected]/requests/validate_body.go:32 +0x16a
github.com/pb33f/libopenapi-validator.(validator).ValidateHttpRequest.func2(0x0?, 0x0?)
/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:247 +0x30
created by github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest in goroutine 3422
/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:267 +0x332`
command used to run wiretap:
wiretap -u https://my-api-server-url.com/ --ws-host localhost -s smoke.json
Given Wiretap as a proxy , Given that there is HTTP rewritting it would be nice to have better logging on the rewrite applied
here i got in wiretap logs this
level=info msg="[wiretap] request /trades: completed (307)" fileName=handle_request.go goroutine=686 package=daemon
would be nice to have received /trades , redirecting to http://ggg:zzz/agivenconfigurepath/toto/trades in the logs
could be also something to put in the UI either
here it s even not clear who reply the 307
looking on the ui , it propose a location https://localhost:8443/trades but looks not clear where does it comes from
As of today the reset state button reset the "call panel" on the left
but it does not reset the statistics about number of call and success
it should (my opinion) or have a way to do it via a tick ( not sure as will make ui with plenty of tick in few years )
When setting WireTap as a validation proxy , it would be nice to return as well the error details to the client and not only the 502
could be returning HTTP RFC problem format or whaterver
meanning instead of empty payload returning something like to have better understanding as well from client point of view.
it should include response violation as well as type and how to fix
(i know all those are in the UI but having them as well in the return would help the debugging lifecycle.
The static dir needs checking before trying to be read.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x28 pc=0x10129b7d0]
goroutine 439 [running]:
github.com/pb33f/wiretap/daemon.MonitorStatic.func1.1({0x16f0fb720, 0xc}, {0x0?, 0x0?}, {0x140006a6c30?, 0x140006a6c00?})
/home/runner/work/wiretap/wiretap/daemon/monitor_static.go:30 +0x30
I suspect this is likely to be a feature request more than a bug. But consider this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
paths:
/anything/requestBodies/post/application/json/simple:
post:
operationId: requestBodyPostApplicationJsonSimple
tags:
- requestBodies
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/simpleObject"
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
title: res
type: object
properties:
json:
$ref: "#/components/schemas/simpleObject"
required:
- json
components:
schemas:
simpleObject:
description: "A simple object that uses all our supported primitive types and enums and has optional properties."
externalDocs:
description: "A link to the external docs."
url: "https://docs.speakeasyapi.dev"
type: object
properties:
str:
type: string
description: "A string property."
example: "test"
bool:
type: boolean
description: "A boolean property."
example: true
int:
type: integer
description: "An integer property."
example: 1
int32:
type: integer
format: int32
description: "An int32 property."
example: 1
num:
type: number
description: "A number property."
example: 1.1
float32:
type: number
format: float
description: "A float32 property."
example: 1.1
enum:
$ref: "#/components/schemas/enum"
date:
type: string
format: date
description: "A date property."
example: "2020-01-01"
dateTime:
type: string
format: date-time
description: "A date-time property."
example: "2020-01-01T00:00:00.000001Z"
any:
description: "An any property."
example: "any"
strOpt:
type: string
description: "An optional string property."
example: "testOptional"
boolOpt:
type: boolean
description: "An optional boolean property."
example: true
intOptNull:
type: integer
description: "An optional integer property will be null for tests."
numOptNull:
type: number
description: "An optional number property will be null for tests."
intEnum:
type: integer
description: "An integer enum property."
enum:
- 1
- 2
- 3
example: 2
x-speakeasy-enums:
- First
- Second
- Third
int32Enum:
type: integer
format: int32
description: "An int32 enum property."
enum:
- 55
- 69
- 181
example: 55
bigint:
type: integer
format: bigint
example: 8821239038968084
bigintStr:
type: string
format: bigint
example: "9223372036854775808"
decimal:
type: number
format: decimal
example: 3.141592653589793
decimalStr:
type: string
format: decimal
example: "3.14159265358979344719667586"
required:
- str
- bool
- int
- int32
- num
- float32
- enum
- date
- dateTime
- any
- intEnum
- int32Enum
enum:
type: string
description: "A string based enum"
enum:
- "one"
- "two"
- "three"
- "four_and_more"
example: "one"
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
The response has properties like:
bigint:
type: integer
format: bigint
example: 8821239038968084
bigintStr:
type: string
format: bigint
example: "9223372036854775808"
decimal:
type: number
format: decimal
example: 3.141592653589793
decimalStr:
type: string
format: decimal
example: "3.14159265358979344719667586"
ie integers and numbers that are using advances formats. decimal is currently a recognized format in the official OpenAPI format registry and we are trying to get bigint
added as well.
currently wiretap just returns nothing for these properties:
{
"json": {
"any": "any",
"bool": true,
"date": "2020-01-01",
"dateTime": "2020-01-01T00:00:00.000001Z",
"enum": "one",
"float32": 1.1,
"int": 1,
"int32": 1,
"int32Enum": 55,
"intEnum": 2,
"num": 1.1,
"str": "test"
}
}
where we need it to return the defined examples at least
'"{ \"Data\": { \"CryptId\": \"****************\", \"Pyro_transactions\": [ ] }, \"Links\": { \"Self\": \"/crypt-information/********/crypt/<uuid>/Pyro_transactions\" }, \"Meta\": { \"TotalPages\": 1 }}"'
error:
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x68 pc=0x1012b45cc]
goroutine 3914 [running]:
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validateValue.func1()
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:178 +0x120
panic({0x101cc5aa0?, 0x1025a6b70?})
/opt/hostedtoolcache/go/1.22.1/x64/src/runtime/panic.go:770 +0x124
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validate(0x0, {0x0, 0x0, 0x0}, 0x0, {0x0, 0x0}, {0x101cb60c0, 0x1400055fad0}, {0x0, ...})
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:253 +0x43c
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).validateValue(0x0, {0x101cb60c0?, 0x1400055fad0?}, {0x0, 0x0})
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:182 +0x94
github.com/santhosh-tekuri/jsonschema/v5.(*Schema).Validate(...)
/home/runner/go/pkg/mod/github.com/santhosh-tekuri/jsonschema/[email protected]/schema.go:168
github.com/pb33f/libopenapi-validator/responses.ValidateResponseSchema(0x140006d4b40, 0x140005263f0, 0x14000554508, {0x14000f3e000, 0xfdc5, 0x12000}, {0x14000ff6000, 0x96c6, 0x3?})
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/responses/validate_response.go:132 +0x99c
github.com/pb33f/libopenapi-validator/responses.(*responseBodyValidator).checkResponseSchema(0x14000955b00, 0x140006d4b40, 0x140005263f0, {0x140002b00c0?, 0x14000c42190?}, 0x1400063ab40)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/responses/validate_body.go:140 +0x1fc
github.com/pb33f/libopenapi-validator/responses.(*responseBodyValidator).ValidateResponseBody(0x14000955b00, 0x140006d4b40, 0x140005263f0)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/responses/validate_body.go:54 +0x348
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpResponse(0x140004ec380, 0x140006d4b40, 0x140005263f0)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:116 +0xbc
github.com/pb33f/wiretap/daemon.(*WiretapService).ValidateResponse(0x140009f3040, 0x140004e40c0, 0x140005263f0)
/home/runner/work/wiretap/wiretap/daemon/validate.go:19 +0x6c
created by github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest in goroutine 3612
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:196 +0xa54
This is a bit of a tough one as deepObject
serialization is not very well defined but we support deepObject serialization that is compatible with a number of different server frameworks, but wiretap is failing validation on a request that does work with other services.
Here is the spec (btw this is a distilled down version of the real spec I am using and this distilled version causes this issue #81 so hard to test in isolation and I can't provide the full spec I am using atm):
openapi: 3.1.0
info:
title: Test
version: 0.1.0
paths:
/anything/queryParams/deepObject/map:
get:
operationId: deepObjectQueryParamsMap
parameters:
- name: mapParam
in: query
style: deepObject
schema:
type: object
additionalProperties:
type: string
example: { "test": "value", "test2": "value2" }
required: true
- name: mapArrParam
in: query
style: deepObject
schema:
type: object
additionalProperties:
type: array
items:
type: string
example: { "test": ["test", "test2"], "test2": ["test3", "test4"] }
responses:
"200":
description: OK
The error returned is:
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":500,"detail":"Error: Query parameter 'mapArrParam' is not a valid deepObject, Reason: The query parameter 'mapArrParam' has the 'deepObject' style defined, There are multiple values (2) supplied, instead of a single value, Line: 1498, Column: 18\nError: Query parameter 'mapArrParam' failed to validate, Reason: The query parameter 'mapArrParam' is defined as an object, however it failed to pass a schema validation, Validation Errors: [Reason: expected array, but got string, Location: /additionalProperties/type Reason: expected array, but got string, Location: /additionalProperties/type], Line: 1500, Column: 13"}
The query string being sent is:
"mapArrParam%5Btest2%5D=test3&mapArrParam%5Btest2%5D=test4&mapArrParam%5Btest%5D=test&mapArrParam%5Btest%5D=test2&mapParam%5Btest2%5D=value2&mapParam%5Btest%5D=value"
basically the array is represented by listing the same key multiple times
Allow wiretap to import HAR files and show the replay in the monitor UI, complete with compliance check on OpenAPI spec. I should be able to run this as a headless command and have the tool spit out a compliance report to stout or a file.
Consider this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
paths:
/requestbody#map:
post:
operationId: requestBodyPostApplicationJsonMap
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/mapValue"
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
title: res
type: object
additionalProperties:
$ref: "#/components/schemas/simpleObject"
/requestbody#arrayCamelCase:
post:
operationId: requestBodyPostApplicationJsonArrayCamelCase
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/arrValueCamelCase"
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
title: res
type: array
items:
$ref: "#/components/schemas/simpleObjectCamelCase"
components:
schemas:
arrValueCamelCase:
type: array
items:
$ref: "#/components/schemas/simpleObjectCamelCase"
mapValue:
type: object
additionalProperties:
$ref: "#/components/schemas/simpleObject"
simpleObject:
description: "A simple object that uses all our supported primitive types and enums and has optional properties."
externalDocs:
description: "A link to the external docs."
url: "https://docs.speakeasyapi.dev"
type: object
properties:
str:
type: string
description: "A string property."
example: "test"
bool:
type: boolean
description: "A boolean property."
example: true
int:
type: integer
description: "An integer property."
example: 1
int32:
type: integer
format: int32
description: "An int32 property."
example: 1
num:
type: number
description: "A number property."
example: 1.1
float32:
type: number
format: float
description: "A float32 property."
example: 1.1
enum:
$ref: "#/components/schemas/enum"
date:
type: string
format: date
description: "A date property."
example: "2020-01-01"
dateTime:
type: string
format: date-time
description: "A date-time property."
example: "2020-01-01T00:00:00.000001Z"
any:
description: "An any property."
example: "any"
strOpt:
type: string
description: "An optional string property."
example: "testOptional"
boolOpt:
type: boolean
description: "An optional boolean property."
example: true
intOptNull:
type: integer
description: "An optional integer property will be null for tests."
numOptNull:
type: number
description: "An optional number property will be null for tests."
intEnum:
type: integer
description: "An integer enum property."
enum:
- 1
- 2
- 3
example: 2
x-speakeasy-enums:
- First
- Second
- Third
int32Enum:
type: integer
format: int32
description: "An int32 enum property."
enum:
- 55
- 69
- 181
example: 55
bigint:
type: integer
format: bigint
example: 8821239038968084
bigintStr:
type: string
format: bigint
example: "9223372036854775808"
decimal:
type: number
format: decimal
example: 3.141592653589793
decimalStr:
type: string
format: decimal
example: "3.14159265358979344719667586"
required:
- str
- bool
- int
- int32
- num
- float32
- enum
- date
- dateTime
- any
- intEnum
- int32Enum
simpleObjectCamelCase:
description: "A simple object that uses all our supported primitive types and enums and has optional properties."
externalDocs:
description: "A link to the external docs."
url: "https://docs.speakeasyapi.dev"
type: object
properties:
str_val:
type: string
description: "A string property."
example: "example"
bool_val:
type: boolean
description: "A boolean property."
example: true
int_val:
type: integer
description: "An integer property."
example: 999999
int32_val:
type: integer
format: int32
description: "An int32 property."
example: 1
num_val:
type: number
description: "A number property."
example: 1.1
float32_val:
type: number
format: float
description: "A float32 property."
example: 2.2222222
enum_val:
$ref: "#/components/schemas/enum"
date_val:
type: string
format: date
description: "A date property."
example: "2020-01-01"
date_time_val:
type: string
format: date-time
description: "A date-time property."
example: "2020-01-01T00:00:00Z"
any_val:
description: "An any property."
example: "any example"
str_opt_val:
type: string
description: "An optional string property."
example: "optional example"
bool_opt_val:
type: boolean
description: "An optional boolean property."
example: true
int_opt_null_val:
type: integer
description: "An optional integer property will be null for tests."
example: 999999
num_opt_null_val:
type: number
description: "An optional number property will be null for tests."
example: 1.1
int_enum_val:
type: integer
description: "An integer enum property."
enum:
- 1
- 2
- 3
example: 3
x-speakeasy-enums:
- First
- Second
- Third
int32_enum_val:
type: integer
format: int32
description: "An int32 enum property."
enum:
- 55
- 69
- 181
example: 69
bigint_val:
type: integer
format: bigint
bigint_str_val:
type: string
format: bigint
decimal_val:
type: number
format: decimal
required:
- str_val
- bool_val
- int_val
- int32_val
- num_val
- float32_val
- enum_val
- date_val
- date_time_val
- any_val
- int_enum_val
- int32_enum_val
enum:
type: string
description: "A string based enum"
enum:
- "one"
- "two"
- "three"
- "four_and_more"
example: "one"
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
When sending the request body like so:
[{"any_val":"any","bigint_str_val":"1344719667586153181419716641724567886890850696275767987106294472017884974410332069524504824747437757","bigint_val":8821239038968084,"bool_opt_val":true,"bool_val":true,"date_time_val":"2020-01-01T00:00:00.000000001Z","date_val":"2020-01-01","enum_val":"one","float32_val":1.1,"int32_enum_val":55,"int32_val":1,"int_enum_val":2,"int_val":1,"num_val":1.1,"str_opt_val":"testOptional","str_val":"test"}]
I get this error from wiretap:
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":500,"detail":"Error: POST request body for '/requestbody' failed to validate schema, Reason: The request body is defined as an object. However, it does not meet the schema requirements of the specification, Validation Errors: [Reason: expected object, but got array, Location: /type], Line: 55, Column: 7"}
I believe this is related to #78
Basically I think its validating against the wrong operation and it seems to be non-deterministic (prob due to map order in Go) as sometimes I start wiretap and it works and sometimes I start it and it doesn't work.
I imagine this would be sorted by looping through all operations that match the path instead of just the first found?
This is related to this new change I believe: #78
For this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
- apiKeyAuthNew: []
- oauth2: []
- {}
paths:
/auth#basicAuth:
post:
operationId: basicAuthNew
security:
- basicAuth: []
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/authServiceRequestBody"
required: true
responses:
"200":
description: OK
"401":
description: Unsuccessful authentication.
/auth#apiKeyAuthGlobal:
post:
operationId: apiKeyAuthGlobalNew
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/authServiceRequestBody"
required: true
responses:
"200":
description: OK
"401":
description: Unsuccessful authentication.
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
x-speakeasy-example: YOUR_USERNAME;YOUR_PASSWORD
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
x-speakeasy-example: Token YOUR_API_KEY
bearerAuth:
type: http
scheme: bearer
x-speakeasy-example: YOUR_JWT
apiKeyAuthNew:
type: apiKey
in: header
name: x-api-key
x-speakeasy-example: Token <YOUR_API_KEY>
oauth2:
type: oauth2
flows:
implicit:
authorizationUrl: http://localhost:35123/oauth2/authorize
scopes: {}
x-speakeasy-example: Bearer YOUR_OAUTH2_TOKEN
openIdConnect:
type: openIdConnect
openIdConnectUrl: http://localhost:35123/.well-known/openid-configuration
x-speakeasy-example: Bearer YOUR_OPENID_TOKEN
schemas:
authServiceRequestBody:
type: object
properties:
headerAuth:
type: array
items:
type: object
properties:
headerName:
type: string
expectedValue:
type: string
required:
- headerName
- expectedValue
basicAuth:
type: object
properties:
username:
type: string
password:
type: string
required:
- username
- password
Trying to do a request against the operation apiKeyAuthGlobalNew
fails with the below error:
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":401,"detail":"basic authentication failed: bearer token not found, no `Authorization` header found in request"}
It looks to not be matching the right route and expecting the basic auth of the basicAuthNew
operation
Would be great if you could control status code wiretap returned in mock mode via a header maybe something like x-wiretap-status-code
Consider this example spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/auth#basicAuth:
post:
operationId: basicAuth
security:
- basicAuth: []
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schemas:
type: object
required: true
responses:
"200":
description: OK
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
wiretap will return the below error when sending a request to /auth
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":404,"detail":"Error: POST Path '/auth' not found, Reason: The POST request contains a path of '/auth' however that path, or the POST method for that path does not exist in the specification"}
Using a fragment in the OpenAPI spec is a pretty common way of reusing a path multiple times ie /auth#instance1
and /auth#instance2
so for the same path & method combination a different schema can be provided instead of needing to use oneOf
for example on the request/response bodies.
Is there a way to proxy different urls to different backends?
I tried setting up multiple instances of wiretap in a docker compose but the monitoring webpage displays the same content
Hi there. Wiretap is panicing when I attempt to access the API gateway URL. I am running version 0.0.18 on Linux x86-64 bit.
I invoked the program with:
wiretap --spec specs/specification.yaml --url https://the-live-domain-in-the-specification.com
Wiretap starts up as expected with:
INFO API Gateway UI booting on port 9090...
INFO Monitor UI booting on port 9091...
INFO [ranch] Yee-Haw! Starting up the ranch's HTTP server at localhost:9092 fileName=server.go goroutine=66 package=server
INFO [ranch] Hot-Dang! Starting up the ranch's STOMP message broker at localhost:9092/ranch fileName=server.go goroutine=67 package=server
โโ wiretap is online! โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| |
| โโ API Gateway โโโโโโโโโโ โโ Monitor UI โโโโโโโโโโโ |
| | http://localhost:9090 | | http://localhost:9091 | |
| โโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโ |
| |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Accessing http://localhost:9091/ gives me the below page:
However, accessing http://localhost:9090/ results in an error:
This page isnโt working
localhost didnโt send any data.
ERR_EMPTY_RESPONSE
...and in the terminal:
2023/07/10 12:31:02 http: panic serving [::1]:45744: runtime error: invalid memory address or nil pointer dereference
goroutine 156 [running]:
net/http.(*conn).serve.func1()
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:1854 +0xbf
panic({0xab69e0, 0x17335b0})
/opt/hostedtoolcache/go/1.20.5/x64/src/runtime/panic.go:890 +0x263
github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest(0xc000098500, 0xc000510540)
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:102 +0x6d6
github.com/pb33f/wiretap/daemon.(*WiretapService).HandleHttpRequest(...)
/home/runner/work/wiretap/wiretap/daemon/wiretap_service.go:78
github.com/pb33f/wiretap/cmd.handleHttpTraffic.func1.1({0x12c1cc0?, 0xc0004c4410}, 0xc0005d8000)
/home/runner/work/wiretap/wiretap/cmd/handle_http_traffic.go:27 +0xe5
net/http.HandlerFunc.ServeHTTP(0xc000600000?, {0x12c1cc0?, 0xc0004c4410?}, 0xc000589950?)
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:2122 +0x2f
net/http.(*ServeMux).ServeHTTP(0xc0005120c0?, {0x12c1cc0, 0xc0004c4410}, 0xc0005d8000)
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:2500 +0x149
github.com/gorilla/handlers.CompressHandlerLevel.func1({0x12c2650, 0xc00014e000}, 0xc0005d8000)
/home/runner/go/pkg/mod/github.com/gorilla/[email protected]/compress.go:148 +0x9e8
net/http.HandlerFunc.ServeHTTP(0x0?, {0x12c2650?, 0xc00014e000?}, 0x46a56e?)
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:2122 +0x2f
net/http.serverHandler.ServeHTTP({0xc00051e2a0?}, {0x12c2650, 0xc00014e000}, 0xc0005d8000)
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:2936 +0x316
net/http.(*conn).serve(0xc00044a120, {0x12c2bc0, 0xc00051e420})
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:1995 +0x612
created by net/http.(*Server).Serve
/opt/hostedtoolcache/go/1.20.5/x64/src/net/http/server.go:3089 +0x5ed
when playing with the tool i got this error after about 500 requests.
Unfortunately the tools does not tell me which request caused the issue.
INFO wiretap is proxying all traffic to 'https://xxxxxxxxxxx'
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x68 pc=0xa4ddca]
goroutine 11173 [running]:
github.com/pb33f/libopenapi-validator/requests.(*requestBodyValidator).ValidateRequestBody(0xc000da9d00, 0xc0004a7b00)
/go/pkg/mod/github.com/pb33f/[email protected]/requests/validate_body.go:32 +0x16a
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest.func2(0xc000f986c0?, 0x0?)
/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:247 +0x30
created by github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest in goroutine 11186
/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:267 +0x346
current behaviour when there is a validation error is that it returns a 502
the enhancement i propose is that the returned payload contains
a structured error containning this list of failures , as well as the payload
this allow to have an off line diagnotics without the usuage of the (nice) UI
context of usage beeing newman + wiretap in CICD
given the fact that in case of error newman log the payload, it allows to understand that there was an error, and then to diagnose
it may requires a dedicated flag
This spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
paths:
/anything/queryParams/deepObject/map:
get:
operationId: deepObjectQueryParamsMap
parameters:
- name: mapParam
in: query
style: deepObject
schema:
type: object
additionalProperties:
type: string
example: { "test": "value", "test2": "value2" }
required: true
- name: mapArrParam
in: query
style: deepObject
schema:
type: object
additionalProperties:
type: array
items:
type: string
example: { "test": ["test", "test2"], "test2": ["test3", "test4"] }
responses:
"200":
description: OK
Seems to cause the below panic:
2024/01/14 13:03:24 http: panic serving 127.0.0.1:40818: runtime error: invalid memory address or nil pointer dereference
goroutine 109 [running]:
net/http.(*conn).serve.func1()
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:1868 +0xb9
panic({0xce4100?, 0x1dbe3b0?})
/opt/hostedtoolcache/go/1.21.5/x64/src/runtime/panic.go:920 +0x270
github.com/pb33f/wiretap/mock.(*ResponseMockEngine).ValidateSecurity(0x1?, 0xc0000d8500?, 0xc000054280?)
/home/runner/work/wiretap/wiretap/mock/mock_engine.go:48 +0x24
github.com/pb33f/wiretap/mock.(*ResponseMockEngine).runWorkflow(0xc000400390, 0xc0000d8500)
/home/runner/work/wiretap/wiretap/mock/mock_engine.go:226 +0x73
github.com/pb33f/wiretap/mock.(*ResponseMockEngine).GenerateResponse(...)
/home/runner/work/wiretap/wiretap/mock/mock_engine.go:43
github.com/pb33f/wiretap/daemon.(*WiretapService).handleMockRequest(0xc0000caa90, 0xc0000344e0, 0xc000196600, 0xc0000d8b00)
/home/runner/work/wiretap/wiretap/daemon/handle_mock.go:31 +0xb3
github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest(0xc0000caa90, 0xc0000344e0)
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:172 +0x12ba
github.com/pb33f/wiretap/daemon.(*WiretapService).HandleHttpRequest(...)
/home/runner/work/wiretap/wiretap/daemon/wiretap_service.go:99
github.com/pb33f/wiretap/cmd.handleHttpTraffic.func1.1({0x166f830?, 0xc0000c4230}, 0xc0000d8500)
/home/runner/work/wiretap/wiretap/cmd/handle_http_traffic.go:27 +0xd5
net/http.HandlerFunc.ServeHTTP(0xc000101400?, {0x166f830?, 0xc0000c4230?}, 0xc000391a38?)
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:2136 +0x29
net/http.(*ServeMux).ServeHTTP(0xc0000521f0?, {0x166f830, 0xc0000c4230}, 0xc0000d8500)
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:2514 +0x142
github.com/pb33f/wiretap/cmd.handleHttpTraffic.func1.CompressHandler.CompressHandlerLevel.func3({0x16704d0, 0xc0004460e0}, 0xc0000d8500)
/home/runner/go/pkg/mod/github.com/gorilla/[email protected]/compress.go:148 +0x69f
net/http.HandlerFunc.ServeHTTP(0x1e0c340?, {0x16704d0?, 0xc0004460e0?}, 0xc000391b50?)
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:2136 +0x29
net/http.serverHandler.ServeHTTP({0xc000400f60?}, {0x16704d0?, 0xc0004460e0?}, 0x6?)
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:2938 +0x8e
net/http.(*conn).serve(0xc0000f23f0, {0x1672020, 0xc0003803f0})
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:2009 +0x5f4
created by net/http.(*Server).Serve in goroutine 86
/opt/hostedtoolcache/go/1.21.5/x64/src/net/http/server.go:3086 +0x5cb
when a request is made
Consider this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- xApiKey: []
- apiKey: []
paths:
/test:
get:
responses:
'200':
description: OK
components:
securitySchemes:
xApiKey:
type: apiKey
in: header
name: x-api-key
apiKey:
type: apiKey
in: header
name: Authorization
this error is returned when making a request:
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":401,"detail":"apiKey not found, no `x-api-key` header found in request"}
The sent request had the Authorization
header set but not the x-api-key
header.
but the security:
security:
- xApiKey: []
- apiKey: []
defines either xApiKey
OR apiKey
can be sent.
And AND relationship is defined like so:
security:
- xApiKey: []
apiKey: []
given the fact that for a given request there is validation of the inbound + validation of the outbound i cannot get how we get to 75%
could be 0 % compliance , if we consider the round trip , could be 50 % if we consider that it is 2 check one succeed , and one fail but not 75%
notice that if i repeat it keeps it to 75%
This may be a bad assumption on my part but I would expect (or want) the responses returned by wiretap in mock mode to use the provided examples if in the spec and only provide truly mocked responses (ie generating responses based on the schema) if there were no provided examples.
If this isn't the intended behavior or my assumption was wrong would be good if it could be configured to react this way?
tested with wiretap_0.0.50_linux_x86_64
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xb7b641]
goroutine 299 [running]:
github.com/pb33f/libopenapi-validator/responses.(*responseBodyValidator).ValidateResponseBody(0xc00012cc00, 0xc000472000, 0xc000291680)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/responses/validate_body.go:51 +0x421
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpResponse(0xc0002f4500, 0xc000309b80?, 0x0?)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:116 +0xd3
github.com/pb33f/wiretap/daemon.(*WiretapService).validateResponse(0xc00032ab40, 0xc000544840, 0xc00026a138?)
/home/runner/work/wiretap/wiretap/daemon/validate.go:19 +0x68
created by github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest in goroutine 418
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:197 +0xdeb
response is e expected 400 error
Related to this (or maybe the same bug not fixed): #84
This spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/anything/queryParams/form/array:
get:
x-speakeasy-test: true
operationId: formQueryParamsArray
tags:
- parameters
parameters:
- name: arrParam
in: query
explode: false
schema:
type: array
items:
type: string
examples:
- test
- test2
- name: arrParamExploded
in: query
explode: true
schema:
type: array
items:
type: integer
examples:
- 1
- 2
responses:
"200":
description: OK
content:
application/json:
schema:
title: res
type: object
properties:
url:
type: string
example: http://localhost:35123/anything/queryParams/form/array?arrParam=test%2Ctest2&arrParamExploded=1&arrParamExploded=2
args:
type: object
properties:
arrParam:
type: string
example: "test,test2"
arrParamExploded:
type: array
items:
type: string
examples:
- "1"
- "2"
required:
- arrParam
- arrParamExploded
required:
- url
- args
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
returns ["gEP"]
or similar for the arrParamExploded
property in the response object where I would expect ["1", "2"]
based on the provided examples
Whenever a synchronous api is being executed the wiretap displays the api in executing status with a loader status, but in between if the user refreshes the wiretap UI, the api request which is being executed vanishes from the UI. Could not post a screenshot of the same as the details are confidential in the UI
Hi there!
Please let me know if this is the wrong way of asking this quest as it's more of a support question than an issue with the project (been using it for 30 min and loving it already)
I'm trying to check how the validations work, so i have an api with an already valid example. I make a request to this endpoint and it works great (all using the mock mode).
Now i go and drop fields from the example that are marked as required in the api spec, at this point i'm expecting that the next request will show up as an error.
The reality is that is that it comes back ok. I've also tested by messing with the types (putting a string in a field that's defined as a bool). This also works ok.
I've been able to trigger the validations by making a bad request with a non valid body and i can see that it works as expected.
Is this the correct behaviour? i was hoping that if a server returns a "bad" response it would show up as a violation, is this because i'm running in mock mode?
(originally posted in Discord under the associated thread https://discord.com/channels/923258363540815912/1126857048273981551/1208217864054636626)
Originally reported with wiretap 0.1.1
Requests to an endpoint fails if the previous request was to an endpoint that does not have the same request type (GET
, POST
, etc). This behavior has been encountered using both Python and curl.
The error I'm getting is:
POST operation request content type 'POST' does not exist.
The path was found, but there was no 'POST' method found in the spec.
How to fix this violation:
Add the missing operation to the contract for the path
Current spec: https://github.com/nichwall/audiobookshelf/blob/collection_routes_openapi_v1/build-docs/swagger-output.json
Testing with the /login
endpoint just using curl to POST
works on a fresh run. However, after running the Python script the same curl POST
to /login
fails with a line number of 296 instead of 354 (so the violations references /api/items/{id}
in the spec instead of /login
).
The Python script makes the following requests (all valid calls from before making the OpenAPI spec):
POST
to /login
(succeeds)GET
to /api/libraries
(fails with missing GET
to line 354, or /login
in spec)GET
to /api/libraries/{id}/items
(succeeds)GET
to /api/items/{id}
(fails with invalid schema, unrelated to this error)Sending the curl POST
to /login
then fails with a missing GET
definition, referencing /api/items/{id}
in spec.
After adding a dummy get
request to the /login
endpoint, the get
request to /api/libraries
immediately afterwards passes validation (but the POST
to /login
after the script will still fail).
Spec without all request types defined on the previous endpoint hit through wiretap.
When sending a request to an operation that defines no security in a document with global security wiretap returns a 401 if a request to that operation doesn't include an auth header.
Here is an example spec that causes the issue:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/anything/no-auth:
get:
operationId: noAuth
security:
- {}
responses:
"200":
description: O
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
Here is the response I get back from wiretap:
{"type":"https://pb33f.io/wiretap/error","title":"unable to serve mocked response","status":401,"detail":"apiKey not found, no `Authorization` header found in request"}
Add a new configuration-driven possibility to fail proxied request-response when the request and/or response don't pass OpenAPI validation.
For example, add a boolean configuration parameter that will trigger to return an unsuccessful status code from wiretap when a request and/or response don't pass OpenAPI validation. Maybe, the second configuration parameter with error status code.
Goal - use wiretap in the pipeline with any API mock and get an error when mocked request and/or response don't pass OpenAPI validation
Consider this spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
security:
- apiKeyAuth: []
paths:
/anything/queryParams/form/camelObj:
get:
x-speakeasy-test: true
operationId: formQueryParamsCamelObject
tags:
- parameters
parameters:
- name: obj_param_exploded
in: query
explode: true
schema:
type: object
properties:
search_term:
type: string
example: foo
item_count:
type: string
example: "10"
required: true
- name: obj_param
in: query
explode: false
schema:
type: object
properties:
encoded_term:
type: string
example: bar
encoded_count:
type: string
example: "11"
responses:
"200":
description: OK
content:
application/json:
schema:
title: res
type: object
properties:
url:
type: string
example: http://localhost:35123/anything/queryParams/form/camelObj?item_count=10&obj_param=encoded_count%2C11%2Cencoded_term%2Cbar&search_term=foo
x-speakeasy-test-internal-directives:
- sortQueryParameters: {}
args:
type: object
properties:
search_term:
type: string
example: "foo"
item_count:
type: string
example: "10"
required:
- search_term
- item_count
required:
- url
- args
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Authenticate using an API Key generated via our platform.
And a url to call it like http://localhost:35123/anything/queryParams/form/camelObj?item_count=10&obj_param=encoded_count%2C11%2Cencoded_term%2Cbar&search_term=foo
This request fails with the below error from wiretap:
{
"type": "https://pb33f.io/wiretap/errors#validation_failed_and_spec_insufficient_error",
"title": "Invalid request, specification is insufficient (500)",
"status": 500,
"detail": "The request failed validation, and the specification does not contain a '422' or '400' response for this operation. Check payload for validation errors.",
"payload": [
{
"message": "Query array parameter 'obj_param_exploded' failed to validate",
"reason": "The query parameter (which is an array) 'obj_param_exploded' is defined as an object, however it failed to pass a schema validation",
"validationType": "parameter",
"validationSubType": "query",
"specLine": 1066,
"specColumn": 13,
"howToFix": "Ensure that the object being submitted, matches the schema correctly",
"validationErrors": [
{
"reason": "expected string, but got number",
"location": "/properties/item_count/type"
}
]
}
]
}
This should be a valid request and I wouldn't expect it to fail, especially as the validation error doesn't really seem to be calling out anything valid
type: string
nullable: true
Specification:
properties:
speakerId:
nullable: true
type: string
nullable true is not handled correctly.
For this example spec:
openapi: 3.1.0
info:
title: Test
version: 0.1.0
paths:
/auth:
post:
operationId: basicAuth
security:
- basicAuth: []
servers:
- url: http://localhost:35456
requestBody:
content:
application/json:
schemas:
type: object
required: true
responses:
"200":
description: OK
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
I get the following error:
{"type":"https://pb33f.io/wiretap/errors#build_mock_error","title":"Media type not supported (415)","status":415,"detail":"The media type requested 'application/json' is not supported by this operation"}
It is not clear what this is referring to or why it is failing.
The request as far as I can tell is valid.
Looking into the monitor it does say this about the request body:
Content Type: application/json
[unable to parse JSON body]
the request body being sent is:
{"basicAuth":{"password":"testPass","username":"testUser"}}
with the request content type set to application/json
When clicking around in the monitor to inspect requests, the Body
option is correctly greyed out when switching to the DELETE
request. However, if the previous view was the Body
option of a request which had a Body, the bottom view does not reset/clear and instead shows the error JSON.parse: unexpected character at line 1 column 1 of the JSON data
(what is shown in the screenshot).
Expected behavior is something to the effect of "Field does not exist for request" instead of showing a parse error. I'm not sure if the view should reset to the first valid option (like Query
), since users will probably expect the same option to be selected when switching back to a request which does have a Body
.
This occurs in wiretap 0.1.1.
Something seems to have broken in v0.1.0 release.
Routing requests to an RT server running on localhost:
$ podman run --rm --publish 9090:9090 --publish 9091:9091 --publish 9092:9092 --volume $PWD:/work:rw pb33f/wiretap:v0.1.0 --spec my_spec.yaml --url https://host.containers.internal
...
INFO wiretap is proxying all traffic to 'https://host.containers.internal'
INFO [wiretap] Re-writing path 'https://host.containers.internal/REST/2.0/rt' to '/REST/2.0/rt'
The info about the rewrite appears only after making a request, doesn't seem to matter which one.
And the response is:
{
"type": "https://pb33f.io/wiretap/error",
"title": "Unable to call API",
"status": 500,
"detail": "Get \"/REST/2.0/rt\": unsupported protocol scheme \"\"",
"payload": null
}
Same thing works fine in v0.0.49 and doesn't inform of any rewrites.
would be great if wiretap could validate the request included values that matched the examples in the spec.
Some way to configure wiretap to turn on example validation and ensure that the request contained one of the examples
PS D:\tmp\developer-portal> npm i -g @pb33f/openapi-changes
npm ERR! code 1
npm ERR! path C:\Users\XXX\AppData\Roaming\npm\node_modules@pb33f\openapi-changes
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node ./npm-install/postinstall.js
npm ERR! fetching from URL https://github.com/pb33f/openapi-changes/releases/download/v0.0.53/openapi-changes_0.0.53_windows_x86_64.zip
npm ERR! Error: ENOENT: no such file or directory, chmod './bin/openapi-changes'
npm ERR! at Module.chmodSync (node:fs:1916:3)
npm ERR! at install (file:///C:/Users/XXX/AppData/Roaming/npm/node_modules/@pb33f/openapi-changes/npm-install/postinstall.js:54:14)
npm ERR! at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
npm ERR! errno: -4058,
npm ERR! syscall: 'chmod',
npm ERR! code: 'ENOENT',
npm ERR! path: './bin/openapi-changes'
npm ERR! }
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\XXX\AppData\Local\npm-cache_logs\2024-01-25T11_16_47_112Z-debug-0.log
The panic was:
::1 - - [21/Nov/2023:14:39:49 +0000] "GET /ranch HTTP/1.1" 200 0 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x9a42f7]
goroutine 4338 [running]:
github.com/pb33f/libopenapi/datamodel/high/base.(*SchemaProxy).Schema(0x0)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/datamodel/high/base/schema_proxy.go:77 +0x17
github.com/pb33f/libopenapi-validator/paths.comparePaths({0xc0016364c0?, 0x4, 0x1?}, {0xc001636380?, 0x4, 0x4}, {0xc0003ec138, 0x1, 0x4107c5?}, {0xc0024007a0, ...})
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/paths/paths.go:267 +0x37f
github.com/pb33f/libopenapi-validator/paths.FindPath(0xc002380a00, 0xc002292000)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/paths/paths.go:66 +0x5fb
github.com/pb33f/libopenapi-validator.(*validator).ValidateHttpRequest(0xc000be4400, 0xc002380a00)
/home/runner/go/pkg/mod/github.com/pb33f/[email protected]/validator.go:164 +0x4b
github.com/pb33f/wiretap/daemon.(*WiretapService).validateRequest(0xc001dc2d20, 0xc00174e300, 0xc0023688d0?)
/home/runner/work/wiretap/wiretap/daemon/validate.go:52 +0x62
created by github.com/pb33f/wiretap/daemon.(*WiretapService).handleHttpRequest in goroutine 4336
/home/runner/work/wiretap/wiretap/daemon/handle_request.go:160 +0xa6e
The command used:
wiretap -s ./tests/specs/test_primary.yaml -x -b ./tests/specs -p 35123
I can send you the spec we were using in DM on discord if you need it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.