mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.61k stars 1.08k forks source link

Creating expectations from OpenAPI without components section #1867

Closed ahasbini closed 5 months ago

ahasbini commented 6 months ago

Describe the issue Loading an openapi spec will throw a NullPointerException if the spec:

An openapi spec without component section is valid, but mockserver fails to handle this case.

What you are trying to do Creating expectations from an openapi YAML file.

MockServer version mockserver-netty-5.14.0-shaded.jar

To Reproduce Steps to reproduce the issue:

  1. Examples files:
    example-without-components.yaml
openapi: 3.0.0
info:
  title: 'Mockserver Component Test'
  version: 0.0.1

servers:
  - url: 'http://api.example.com/'

paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            maximum: 100
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                type: array
                maxItems: 100
                items:
                  type: object
                  required:
                    - id
                    - name
                  properties:
                    id:
                      type: integer
                      format: int64
                    name:
                      type: string
                    tag:
                      type: string
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - id
                - name
              properties:
                id:
                  type: integer
                  format: int64
                name:
                  type: string
                tag:
                  type: string
        required: true
      responses:
        '201':
          description: Null response

example-with-components.yaml ```yaml openapi: 3.0.0 info: title: 'Mockserver Component Test' version: 0.0.1 servers: - url: 'http://api.example.com/' paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: '200': description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: type: array maxItems: 100 items: type: object required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string post: summary: Create a pet operationId: createPets tags: - pets requestBody: content: application/json: schema: type: object required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string required: true responses: '201': description: Null response components: schemas: Empty: type: string ```
  1. Start the mockserver (on Windows, note: slf4j-simple-1.7.36.jar needs to be placed in same folder with yaml files and mockserver jar file):
java .;slf4j-simple-1.7.36.jar;mockserver-netty-5.14.0-shaded.jar org.mockserver.cli.Main -serverPort 1080 -logLevel INFO
  1. Create expectations using yam file (from classpath):
curl -v -X PUT "http://localhost:1080/mockserver/openapi" -d'{
    "specUrlOrPayload": "example-without-components.yaml"
}'

OR

curl -v -X PUT "http://localhost:1080/mockserver/openapi" -d'{
    "specUrlOrPayload": "example-with-components.yaml"
}'

Expected behaviour

With example-with-components.yaml ``` [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 started on port: 1080 [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 creating expectation: { "httpRequest" : { "operationId" : "listPets", "specUrlOrPayload" : "example-with-components.yaml" }, "httpResponse" : { "statusCode" : 200, "headers" : { "x-next" : [ "some_string_value" ], "content-type" : [ "application/json" ] }, "body" : [ { "id" : 0, "name" : "some_string_value", "tag" : "some_string_value" } ] }, "id" : "ffffffff-ecef-6ecc-ffff-ffffecef6ecc", "priority" : 0, "timeToLive" : { "unlimited" : true }, "times" : { "unlimited" : true } } with id: ffffffff-ecef-6ecc-ffff-ffffecef6ecc [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 creating expectation: { "httpRequest" : { "operationId" : "createPets", "specUrlOrPayload" : "example-mockserver-with-components.yaml" }, "httpResponse" : { "statusCode" : 201 }, "id" : "ffffffff-d9de-dd98-ffff-ffffd9dedd98", "priority" : 0, "timeToLive" : { "unlimited" : true }, "times" : { "unlimited" : true } } with id: ffffffff-d9de-dd98-ffff-ffffd9dedd98 ```

MockServer Log

With example-without-components.yaml ``` [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 started on port: 1080 [MockServer-EventLog0] ERROR org.mockserver.log.MockServerEventLog - 1080 exception processing { "method" : "PUT", "path" : "/mockserver/openapi", "headers" : { "content-length" : [ "53" ], "content-encoding" : [ ".*" ], "User-Agent" : [ "curl/7.88.1" ], "Host" : [ "localhost:1080" ], "Content-Type" : [ "application/x-www-form-urlencoded" ], "Accept" : [ "*/*" ] }, "keepAlive" : true, "secure" : false, "localAddress" : "localhost/127.0.0.1:1080", "remoteAddress" : "127.0.0.1", "body" : { "type" : "STRING", "string" : "{\n \"specUrlOrPayload\": \"example-without-components.yaml\"\n}", "contentType" : "application/x-www-form-urlencoded" } } java.lang.NullPointerException at org.mockserver.openapi.OpenAPIConverter.lambda$null$6(OpenAPIConverter.java:85) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at org.mockserver.openapi.OpenAPIConverter.lambda$null$7(OpenAPIConverter.java:79) at java.util.Optional.ifPresent(Optional.java:159) at org.mockserver.openapi.OpenAPIConverter.lambda$buildHttpResponse$11(OpenAPIConverter.java:78) at java.util.Optional.ifPresent(Optional.java:159) at org.mockserver.openapi.OpenAPIConverter.buildHttpResponse(OpenAPIConverter.java:70) at org.mockserver.openapi.OpenAPIConverter.lambda$buildExpectations$2(OpenAPIConverter.java:52) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at org.mockserver.openapi.OpenAPIConverter.buildExpectations(OpenAPIConverter.java:62) at org.mockserver.mock.HttpState.add(HttpState.java:247) at org.mockserver.mock.HttpState.handle(HttpState.java:618) at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:96) at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:48) at shaded_package.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at shaded_package.io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at org.mockserver.dashboard.DashboardWebSocketHandler.channelRead(DashboardWebSocketHandler.java:137) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at org.mockserver.netty.websocketregistry.CallbackWebSocketServerHandler.channelRead(CallbackWebSocketServerHandler.java:57) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299) at shaded_package.io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at org.mockserver.netty.unification.PortUnificationHandler.switchToHttp(PortUnificationHandler.java:279) at org.mockserver.netty.unification.PortUnificationHandler.decode(PortUnificationHandler.java:153) at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510) at shaded_package.io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366) at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at shaded_package.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at shaded_package.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at shaded_package.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) at shaded_package.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) at shaded_package.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at shaded_package.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at java.lang.Thread.run(Thread.java:745) ```
ahasbini commented 5 months ago

Closed, duplicate of https://github.com/mock-server/mockserver/issues/1446