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

Supposely unmatched request always default to an expectation #1423

Open gbmarc1 opened 2 years ago

gbmarc1 commented 2 years ago

Describe the issue I have an openapi spec that creates multiple expectations. When calling an endpoint that does not exist (that does should not match any expectation), I would assume that the mock server would return 404. However, it always returns a reponse of a specific expectation that does NOT match.

For example: Request: curl --user name:password -v GET "http://localhost:1080/idontexists"

Response:


*   Trying 127.0.0.1:1080...
* Connected to localhost (127.0.0.1) port 1080 (#0)
* Server auth using Basic with user 'name'
> GET /idontexists HTTP/1.1
> Host: localhost:1080
> Authorization: Basic bmFtZTpwYXNzd29yZA==
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
< content-type: application/json
< connection: keep-alive
< content-length: 648
<
{
    "fileId" : 0,
    "name" : "some_string_value",
    "projectId" : 0,
    "dataOwnerId" : 0,
    "language" : "some_string_value",
    "territory" : "some_string_value",
    "importType" : "comment",
    "workUnitId" : 0,
    "totalSubmittedData" : 0,
    "totalUniqueData" : 0,
    "createdDatumParts" : 0,
    "createdData" : 0,
    "createdProjectData" : 0,
    "createdWorkUnitData" : 0,
    "createdOnWorkUnitData" : "2018-11-13T20:20:39+00:00",
    "createdOn" : "2018-11-13T20:20:39+00:00",
    "modifiedOn" : "2018-11-13T20:20:39+00:00",
    "expiredOn" : "2018-11-13T20:20:39+00:00",
    "status" : "import-submitted",
    "progress" : 1.5,
    "error" : "some_string_value"
}* Connection #0 to host localhost left intact

The default response comes from a "not supported" operation that is added. It seems that its response becomes the default when not found.

multipart form data is not supported on requestBody, skipping operation:    "v1.datamgmt.projects.projectId.workUnit.workUnitId.workUnitData.files.post"    method: "POST"  in open api:    

If I remove that operation in the .yaml file, the mock server behaves properly.

MockServer version I used mockserver/mockserver:mockserver-5.13.2 and mockserver/mockserver:latest and both have the same behaviour.

MockServer Log

{
  "method": "GET",
  "path": "/idontexists",
  "headers": {
    "content-length": [
      "0"
    ],
    "User-Agent": [
      "curl/7.83.1"
    ],
    "Host": [
      "localhost:1080"
    ],
    "Authorization": [
      "Basic bmFtZTpwYXNzd29yZA=="
    ],
    "Accept": [
      "*/*"
    ]
  },
  "keepAlive": true,
  "secure": false,
  "remoteAddress": "172.17.0.1"
}
karu971 commented 2 years ago

Got the same issue...

jamesdbloom commented 2 years ago

I can't reproduce this even with an OpenAPI specification with a multipart/form-data field.

Perhaps there is an issue related to your specific OpenAPI specification or your specification includes a request that would match the curl you're making.

Please provide the specification so I can test with that.

gimbimloki commented 1 year ago

Hi, I get the same issue.

If content is multipart/form-data, httpRequestPropertiesMatcher is not added to httpRequestPropertiesMatchers. https://github.com/mock-server/mockserver/blob/master/mockserver-core/src/main/java/org/mockserver/matchers/HttpRequestsPropertiesMatcher.java#L438

            if (contentType.equals("multipart/form-data")) {
                logEntries.add(
                    new LogEntry()
                        .setLogLevel(ERROR)
                        .setMessageFormat("multipart form data is not supported on requestBody, skipping operation:{}method:{}in open api:{}")
                        .setArguments(methodOperationPair.getRight().getOperationId(), methodOperationPair.getLeft(), openAPIDefinition)
                );
                return;
            }

When httpRequestPropertiesMatchers is empty, always return true. https://github.com/mock-server/mockserver/blob/master/mockserver-core/src/main/java/org/mockserver/matchers/HttpRequestsPropertiesMatcher.java#L504

    public boolean matches(MatchDifference context, RequestDefinition requestDefinition) {
        boolean result = false;
        if (httpRequestPropertiesMatchers != null && !httpRequestPropertiesMatchers.isEmpty()) {
            for (HttpRequestPropertiesMatcher httpRequestPropertiesMatcher : httpRequestPropertiesMatchers) {
                if (context == null) {
                    if (MockServerLogger.isEnabled(Level.TRACE) && requestDefinition instanceof HttpRequest) {
                        context = new MatchDifference(configuration.detailedMatchFailures(), requestDefinition);
                    }
                    result = httpRequestPropertiesMatcher.matches(context, requestDefinition);
                } else {
                    MatchDifference singleMatchDifference = new MatchDifference(configuration.detailedMatchFailures(), context.getHttpRequest());
                    result = httpRequestPropertiesMatcher.matches(singleMatchDifference, requestDefinition);
                    context.addDifferences(singleMatchDifference.getAllDifferences());
                }
                if (result) {
                    break;
                }
            }
        } else {
            result = true;
        }
        return result;
    }

I think also multipart/form-data has to have httpRequestPropertiesMatcher.