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

API paths generated with two forward slashes #423

Closed
yate opened this issue Aug 22, 2014 · 22 comments
Closed

API paths generated with two forward slashes #423

yate opened this issue Aug 22, 2014 · 22 comments
Labels
Milestone

Comments

@yate
Copy link

yate commented Aug 22, 2014

I'm generating using the default configuration class com.mangofactory.swagger.configuration.SpringSwaggerConfig

swagger-springmvc 0.8.8
spring 3.2.1.RELEASE

My controller is annotated with @Controller with no value
My method endpoints do not start with /
My DispatcherServlet is mapped to / in my web.xml
The context root of the ear (I have two wars in my ear) i'm deploying is /services/agr

I've tried to debug this and i've gotten here in ApiListingReferenceScanner line 97

String path = swaggerPathProvider.getResourceListingPath(swaggerGroup, resourceGroupName);
log.info("Created resource listing Path: {} Description: {} Position: {}", path, resourceGroupName, position);

swaggerGroup = default
resourceGroupName = agreement

this path comes back as //default/agreement but I can't figure out why, I would like it to be /default/agreement/.

apis: [
 {
   path: "//default/agreement",
   description: "agreement"
 }
]
@yate
Copy link
Author

yate commented Aug 22, 2014

I"m debugging more and it's coming down to this method in org.springframework.web.util.HierarchicalUriComponents

public String getPath() {
    StringBuilder pathBuilder = new StringBuilder();
    for (PathComponent pathComponent : this.pathComponents) {
        pathBuilder.append(pathComponent.getPath());
    }
    return pathBuilder.toString();
}

It has two path components, a FullPathComponent and a PathSegmentComponent. The getPath() of FullPathComponent is / from the getDocumentationPath() call in SwaggerPathProvider line 89. The PathSegmentComponent contains "default" and "agreement" and its getPath() returns /default/agreement/. Put those together and it becomes //default/agreement. How can this behavior be changed?

@adrianbk
Copy link
Member

it was this commit 7f15055

@dilipkrish what was the context around this change? I understood that the relativepathprovider was working as intended prior to this change?

@dilipkrish
Copy link
Member

There was a bug #411 which I verified in the demo project as well. It was to fix that issue.

The problem wa that while the swagger ui would come up fine. The requests URL that the "try" button would generate was incorrect.

@yate
Copy link
Author

yate commented Sep 2, 2014

Is there a workaround I can do using SwaggerSpringMvcPlugin for now, is it possible to set ROOT in RelativeSwaggerPathProvider to an empty string?

@adrianbk
Copy link
Member

adrianbk commented Sep 2, 2014

yo u can implement your own swaggerpathprovider and pass it to your SwaggerSpringMvcPlugin instance.

@yate
Copy link
Author

yate commented Sep 2, 2014

Thanks adrian, I ended up using that solution and it worked for some of the paths but not all. I think the specific endpoint paths for each method still had the two slashes. I'll look into it more tomorrow at work.

@adrianbk
Copy link
Member

adrianbk commented Sep 2, 2014

I think its a bug with the logic that builds the path - we need a test and fix for double slashes.

@yate
Copy link
Author

yate commented Sep 4, 2014

I was able to get it working with the follow path provider implementation. Specifically getDocumentationPath and getOperationPath were the ones adding the extra slashes.

import org.springframework.web.util.UriComponentsBuilder;

import com.mangofactory.swagger.paths.SwaggerPathProvider;

public class AgreementPathProvider extends SwaggerPathProvider {

    private String apiResourcePrefix = "";

    public String getApiResourcePrefix() {
        return apiResourcePrefix;
    }

    public void setApiResourcePrefix(String apiResourcePrefix) {
        Assert.notNull(apiResourcePrefix);
        Assert.isTrue(!apiResourcePrefix.startsWith("/"));
        Assert.isTrue(!apiResourcePrefix.endsWith("/"));
        this.apiResourcePrefix = apiResourcePrefix;
    }
    @Override
    protected String applicationPath() {
        return "/services/agr";
    }

    @Override
    protected String getDocumentationPath() {
        return "";
    }

    @Override
    public String getOperationPath(String operationPath) {
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("");
        if (!isBlank(apiResourcePrefix)) {
            uriComponentsBuilder.path(apiResourcePrefix);
        }
        return uriComponentsBuilder.path(operationPath).build().toString();
    }
}

@yate
Copy link
Author

yate commented Sep 4, 2014

Scratch that. The URLs look correct but the actual request url in swagger-ui is wrong. I'll keep playing around with it.

@adrianbk
Copy link
Member

adrianbk commented Sep 4, 2014

you could wrap/decorate relativeswaggerpathprovider and do a replaceall '//' with '/'

@yate
Copy link
Author

yate commented Sep 5, 2014

I was able to get the whole thing working by returning my context path in applicationPath(), i put my edits in the code above.

@dilipkrish
Copy link
Member

@yate Thats exactly what the RelativeSwaggerPathProvider does. Are you by any chance having dynamic servlets?

@yate
Copy link
Author

yate commented Sep 5, 2014

No I don't believe so. I have one dispatcher servlet defined in my web.xml which is mapped to /, i'm also using <mvc:default-servlet-handler /> in my spring context to enable static file serving.

The only difference between my path provider and the relative path provider is that getDocumentationPath returns an empty String instead of / and
UriComponentsBuilder.fromPath(""); uses an empty string instead of /

@simplyDoingIT
Copy link

I am too facing this issue. And my analysis is also indicating to me that RelativeSwaggerPathProvider's getDocumentationPath() or applicationPath() is causing the issue. Will chip in with more info in some time.

@adrianbk
Copy link
Member

@simplyDoingIT @yate can you try the latest 0.9.0-SNAPSHOT snapshot. I'm guessing its some bug with some earlier version of springs UriComponents.. The following commit should fix the issue: e359280

@simplyDoingIT
Copy link

@adrianbk I do not have gradle set up. I spend couple of hours setting it up however, I could not make a breakthrough through the proxies that we have. Thus, I may have to wait until a release is done by you for testing it. If you can provide me with the compiled jar, may be then I can locally install it and attempt testing.

@simplyDoingIT
Copy link

@adrianbk I was able to compile the project. And publish project in my local maven repository.
However, I am getting compile time issues when I include the swagger-springmvc dependency with 0.0.9-snapshot version.
The message is

  package com.wordnik.swagger.annotations does not exist
  package com.wordnik.swagger.model does not exist

It is unable to identify Swagger annotations and swagger model which are essentially made available transitively by swagger-springmvc.

On comparing the pom.xmls of swagger-springmvc with version 0.8.8 and 0.0.9-Snapshot, I noticed that all dependencies in 0.0.9-snapshot are having scope runtime. I am guessing that is why compilation is failing. Kindly remove the runtime scope. then I will be able to test it successfully.

Thanks in advance.

adrianbk added a commit that referenced this issue Oct 12, 2014
@adrianbk
Copy link
Member

@simplyDoingIT the latest 0.9.0-snapshot should have a fix. It's an issue with the gradle publishing mechanism we are using

Good work catching this 👍

Our next release will be the first one using (gradle/jcenter) [https://github.com//issues/422] so it's great to have someone finding these issues early.

@simplyDoingIT
Copy link

@adrianbk I did the testing after the fix you did for pom's runtime issue.
Earlier I was getting the url
http://localhost:7070/rest/api-docs//apiGrouping/apideclaration1

After your change for fixing the double slash, my url started coming as

http://localhost:7070/rest/api-docs/apiGrouping/apideclaration1

Your couple of fixes worked fine. This issue can be closed. Thanks a lot for your support. Eagerly waiting for you to make the next release with these two fixes included

Adding @yate in the loop.

@simplyDoingIT
Copy link

@adrianbk I here by would like to appreciate you for providing SpringSwaggerConfig as a composition element rather than inheritance. It has been a instructing example for preference of composition over inheritance for me. Thank you to your team.

@yate
Copy link
Author

yate commented Oct 12, 2014

@adrianbk @simplyDoingIT Thanks very much!

@yate yate closed this as completed Oct 12, 2014
@adrianbk adrianbk added this to the 0.9.0 milestone Oct 13, 2014
@adrianbk
Copy link
Member

V0.9.0 released

adrianbk added a commit that referenced this issue Oct 13, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants