BasePath is never used in validator

Issue #40 resolved
Yuda Dai created an issue

Say in swagger, there is "basePath":"/base" and some other method path "/testGet"

If I validate the following it will fail validate(swagger.json, /base/testGet) while if i do not include the base path, it will succeed on validate(swagger.json, /testGet).

To further debug, based on the latest version of swagger-request-validator-core.1.0.13, I find that there is on bug on com.atlassian.oai.validator.interaction.ApiOperationResolver.ApiBasedNormalisedPath#ApiBasedNormalisedPath.

In the constructor, line 93, this.normalised = this.normalise(path);, and inside String normalise(String), it calls trimPrefix at line 133. Inside trimPrefix, it uses member variable apiPrefix but apiPrefix has not been initialized until line 95.

In this case, the normalised string will always use null as apiPrefix.

Comments (8)

  1. Blue-Ledao
    The bug still exists in version swagger-request-validator-core 1.3.2. 
    There is "basePath":"/base" and some other method path "/testGet".
    Whether url contains basepath or does not contains basepath, it will succeed on validate.
    eg:
    swagger.json, /base/testGet, it will succeed on validate.
    swagger.json, /testGet, it will still succeed on validate.
    
  2. Blue-Ledao

    I have updated to version 1.44. I'm sorry the problem still exists.The bug can be seen in my test code:

    /**
     * Created by Blue-Ledao on 2018/6/21.
     */
    public class JunitTest {
    
        String basepath;
        String apipath;
        private String template =
                "{\n" +
                        "  \"swagger\": \"2.0\",\n" +
                        "  \"info\": {\n" +
                        "    \"version\": \"1.0.0\",\n" +
                        "    \"title\": \"Sample API\",\n" +
                        "    \"description\": \"A simple API to learn how to write OpenAPI Specification\"\n" +
                        "  },\n" +
                        "  \"schemes\": [\n" +
                        "    \"https\",\n" +
                        "    \"http\"\n" +
                        "  ],\n" +
                        "  \"host\": \"localhost\",\n" +
                        "  \"basePath\": \"#####\",\n" +
                        "  \"paths\": {\n" +
                        "    \"*****\": {\n" +
                        "      \"get\": {\n" +
                        "        \"responses\": {\n" +
                        "          \"200\": {\n" +
                        "            \"description\": \"ok\"\n" +
                        "          }\n" +
                        "        }\n" +
                        "      }\n" +
                        "    }\n" +
                        "  }\n" +
                        "}";
    
        public String setSwaggerString(String basepath,String apipath){
            String swaggerString = template.replace("#####",basepath).replace("*****",apipath);
            return swaggerString;
        }
    
        public ValidationReport validate(SimpleRequest request){
            String swaggerString = setSwaggerString(basepath, apipath);
            SwaggerRequestResponseValidator validator = SwaggerRequestResponseValidator.createFor(swaggerString).build();
            ValidationReport report = validator.validateRequest(request);
            return report;
        }
    
        /**
         * There is a Simplerequest object in the test1(), and its URL is/test/test
         * If the basepath is the same as apipath in swagger, then test1() does not pass
         * In fact the return value of report.hasErrors() should be false
         */
        @Test
        public void test1(){
            basepath = "/test";
            apipath = "/test";
            SimpleRequest request1 = SimpleRequest.Builder.get("/test/test").build();
            ValidationReport report = validate(request1);
            Assert.assertEquals(false,report.hasErrors());
        }
    
        /**
         * There is a Simplerequest object in the test2(), and its URL is/test/testABC
         * If BasePath is a apipath substring in swagger, then test2() does not pass
         * In fact the return value of report.hasErrors() should be false
         */
        @Test
        public void test2(){
            basepath = "/test";
            apipath = "/testABC";
            SimpleRequest request2 = SimpleRequest.Builder.get("/test/testABC").build();
            ValidationReport report = validate(request2);
            Assert.assertEquals(false,report.hasErrors());
        }
    
        /**
         * There is a Simplerequest object in the test3(), and its URL is/test
         * If the basepath is defined in the swagger, the URL does not actually contain basepath, then test3() does not pass
         * In fact the return value of report.hasErrors() should be true
         */
        @Test
        public void test3(){
            basepath = "/abc";
            apipath = "/test";
            SimpleRequest request3 = SimpleRequest.Builder.get("/test").build();
            ValidationReport report = validate(request3);
            Assert.assertEquals(true,report.hasErrors());
        }
    }
    
  3. James Navin

    Hi @Blue-Ledao - thanks for that test - super helpful.

    Looks like we have two separate bugs going on here:

    For test1 and test2 the problem is that the apipath has the same prefix as the basepath and so gets removed incorrectly. Your tests pass if you change the basepath to something other than test.

    For test3 the problem is that the 'normalized' request path matches the 'normalised' apipath and so the validation succeeds.

    I will raise a new issue to track these bugs.

  4. Log in to comment