Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"SEVERE exception validating JSON" while parsing pathparameter of openapi-generated request matchers #1839

Open
ZeeD opened this issue Feb 5, 2024 · 2 comments

Comments

@ZeeD
Copy link

ZeeD commented Feb 5, 2024

Describe the issue
I have an openapi-spec, the relevant bits are the following one:

{
  "openapi": "3.1.0",
  "info": {
    "title": "Ocellus Query API",
    "version": "0.1.0"
  },
  "paths": {
    "/api/v1/dimensions/{proposition}": {
      "get": {
        "tags": [
          "dimensions"
        ],
        "summary": "Get the dimensions for the given proposition",
        "description": "Return all the dimensions for a particular proposition",
        "operationId": "dimensions_get_api_v1_dimensions__proposition__get",
        "parameters": [
          {
            "name": "proposition",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Proposition"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapper_Dimensions_"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    ....

After using the REST api, mockserver has imported the openapi spec and generated some expectations. The relevant one is:

{
  "httpRequest": {
    "operationId": "dimensions_get_api_v1_dimensions__proposition__get",
    "specUrlOrPayload": "https://query-api-int-us-east-2.ocellus.nbcuni.com/openapi.json",
    "requestMatchers": [
      {
        "method": "GET",
        "path": "/api/v1/dimensions/{proposition}",
        "pathParameters": {
          "keyMatchStyle": "MATCHING_KEY",
          "proposition": {
            "parameterStyle": "SIMPLE",
            "values": [
              {
                "schema": {
                  "title": "Proposition"
                }
              }
            ]
          }
        }
      }
    ]
  },
  "httpResponse": {
    "statusCode": 200,
    "headers": {
      "content-type": [
        "application/json"
      ]
    },
    "body": {
      "data": {}
    }
  },
  "id": "ffffffff-a73b-de81-ffff-ffffa73bde81",
  "priority": 0,
  "timeToLive": {
    "unlimited": true
  },
  "times": {
    "unlimited": true
  }
}

now, if I try to call the endpoint with a number, as proposition, it works:

$ curl http://localhost:54732/api/v1/dimensions/123
{
  "data" : { }
}

but if I use a word, I got a 404 and some errors in the logs

$ curl http://localhost:54732/api/v1/dimensions/foobar -v 
*   Trying [::1]:54732...
* Connected to localhost (::1) port 54732
> GET /api/v1/dimensions/foobar HTTP/1.1
> Host: localhost:54732
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< connection: keep-alive
< content-length: 0
<
* Connection #0 to host localhost left intact
2024-02-05 20:10:38 5.15.0 INFO 1080 received request:
  {
    "method" : "GET",
    "path" : "/api/v1/dimensions/foobar",
    "headers" : {
      "content-length" : [ "0" ],
      "User-Agent" : [ "curl/8.4.0" ],
      "Host" : [ "localhost:54732" ],
      "Accept" : [ "*/*" ]
    },
    "keepAlive" : true,
    "secure" : false,
    "protocol" : "HTTP_1_1",
    "localAddress" : "172.17.0.2:1080",
    "remoteAddress" : "172.17.0.1:55362"
  }
 
2024-02-05 20:10:38 5.15.0 SEVERE exception validating JSON 
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'foobar': was expecting (JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')
 at [Source: (String)"foobar"; line: 1, column: 7]
        at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2418)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:759)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:3038)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:3016)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken2(ReaderBasedJsonParser.java:2806)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2784)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchFalse(ReaderBasedJsonParser.java:2760)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:771)
        at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4759)
        at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3124)
        at org.mockserver.validator.jsonschema.JsonSchemaValidator.isValid(JsonSchemaValidator.java:167)
        at org.mockserver.model.NottableSchemaString.validate(NottableSchemaString.java:199)
        at org.mockserver.model.NottableSchemaString.matches(NottableSchemaString.java:170)
        at org.mockserver.matchers.RegexStringMatcher.matchesBySchemas(RegexStringMatcher.java:73)
        at org.mockserver.matchers.RegexStringMatcher.matches(RegexStringMatcher.java:54)
        at org.mockserver.collections.NottableStringMultiMap.containsAll(NottableStringMultiMap.java:74)
        at org.mockserver.matchers.MultiValueMapMatcher.matches(MultiValueMapMatcher.java:50)
        at org.mockserver.matchers.MultiValueMapMatcher.matches(MultiValueMapMatcher.java:15)
        at org.mockserver.matchers.HttpRequestPropertiesMatcher.matches(HttpRequestPropertiesMatcher.java:498)
        at org.mockserver.matchers.HttpRequestPropertiesMatcher.matches(HttpRequestPropertiesMatcher.java:321)
        at org.mockserver.matchers.HttpRequestPropertiesMatcher.matches(HttpRequestPropertiesMatcher.java:208)
        at org.mockserver.matchers.HttpRequestsPropertiesMatcher.matches(HttpRequestsPropertiesMatcher.java:512)
        at org.mockserver.mock.RequestMatchers.lambda$firstMatchingExpectation$9(RequestMatchers.java:227)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.concurrent.ConcurrentSkipListMap$KeySpliterator.tryAdvance(ConcurrentSkipListMap.java:3176)
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
        at org.mockserver.mock.RequestMatchers.firstMatchingExpectation(RequestMatchers.java:242)
        at org.mockserver.mock.HttpState.firstMatchingExpectation(HttpState.java:269)
        at org.mockserver.mock.action.http.HttpActionHandler.processAction(HttpActionHandler.java:95)
        at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:189)
        at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:51)
        at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at org.mockserver.dashboard.DashboardWebSocketHandler.channelRead(DashboardWebSocketHandler.java:137)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at org.mockserver.netty.websocketregistry.CallbackWebSocketServerHandler.channelRead(CallbackWebSocketServerHandler.java:57)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at org.mockserver.netty.unification.PortUnificationHandler.switchToHttp(PortUnificationHandler.java:335)
        at org.mockserver.netty.unification.PortUnificationHandler.decode(PortUnificationHandler.java:173)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
        at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at java.base/java.lang.Thread.run(Thread.java:833)
2024-02-05 20:10:38 5.15.0 INFO 1080 request:
  {
    "method" : "GET",
    "path" : "/api/v1/dimensions/foobar",
    "headers" : {
      "content-length" : [ "0" ],
      "User-Agent" : [ "curl/8.4.0" ],
      "Host" : [ "localhost:54732" ],
      "Accept" : [ "*/*" ]
    },
    "keepAlive" : true,
    "secure" : false,
    "protocol" : "HTTP_1_1",
    "localAddress" : "172.17.0.2:1080",
    "remoteAddress" : "172.17.0.1:55362"
  }
 didn't match open api "...s-east-2.ocellus.nbcuni.com/openapi.json" operation "dimensions_get_api_v1_dimensions__proposition__get" request matcher:
  {
    "method" : "GET",
    "path" : "/api/v1/dimensions/{proposition}",
    "pathParameters" : {
      "keyMatchStyle" : "MATCHING_KEY",
      "proposition" : {
        "parameterStyle" : "SIMPLE",
        "values" : [ {
          "schema" : {
            "title" : "Proposition"
          }
        } ]
      }
    }
  }
 because:
  method matched
  path matched
  body matched
  headers matched
  cookies matched
  pathParameters didn't match
 
2024-02-05 20:10:38 5.15.0 INFO 1080 no expectation for:
  {
    "method" : "GET",
    "path" : "/api/v1/dimensions/foobar",
    "headers" : {
      "content-length" : [ "0" ],
      "User-Agent" : [ "curl/8.4.0" ],
      "Host" : [ "localhost:54732" ],
      "Accept" : [ "*/*" ]
    },
    "keepAlive" : true,
    "secure" : false,
    "protocol" : "HTTP_1_1",
    "localAddress" : "172.17.0.2:1080",
    "remoteAddress" : "172.17.0.1:55362"
  }
 returning response:
  {
    "statusCode" : 404,
    "reasonPhrase" : "Not Found"
  }

That doesn't seems right to me

MockServer version
I'm using the docker version of mock-server, tagging mockserver/mockserver:latest

@djordjeandrejevic
Copy link

djordjeandrejevic commented Mar 1, 2024

I encountered the exact same issue.

Have you tried downgrading OpenAPI version (from 3.1.0 to 3.0.0)?

That did the trick for me.

Prior to downgrading, I was also importing 3.1.0 OpenAPI spec and only after realizing that Petstore OpenAPI (OpenAPI version 3.0.0) works as expected, I was able to fix this...

@ZeeD
Copy link
Author

ZeeD commented Mar 5, 2024

Keep in mind that the openapi json has been generated from sources (I know that the service relies on python's fastapi project)
I don't know how easy it would be to update the service to generate the openapi specs in a different format, and, btw, I don't have direct access to the project.
Do you know any converter I can use locally to change from 3.1.0 to 3.0.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants