How to get Swagger Plugin working within self host

2019-05-17 17:16发布

I've re-asked this question with examples provided on github and a drop box download link for anyone that want to run the code themselves : Swagger not working on a self hosted ServiceStack Service


I had my servicestack JSON service running inside my website solution, under the '/api/ path, but now I'd like to split out that service stack portion and have it running as a self hosted windows service. My problem is, myself and the other developers find the Swagger plugin very useful for testing purposes, but now that it's self hosted it appears the HTTPHandler is setup only for only handling the service routes, and plain HTML does not work.

How do I fix this?

URL : http://localhost:8081/Swagger-UI/Index.html

Response :

Handler for Request not found: 

Request.HttpMethod: GET
Request.HttpMethod: GET
Request.PathInfo: /Swagger-UI/Index.html
Request.QueryString: 
Request.RawUrl: /Swagger-UI/Index.html

Nuget packages installed :

ServiceStack
ServiceStack.Razor

Update for @marfarma

My app.config file has nothing ServiceStack related inside it...

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_service1_V2_SSL" />
        <binding name="BasicHttpBinding_service2_V1_SSL" />
      </basicHttpBinding>
    </bindings>
    <client>
      <!-- bespoke services I'm connecting too -->
    </client>
  </system.serviceModel>
  <appSettings>
     <!-- bespoke app settings -->
  </appSettings>  
</configuration>

Program.cs :

           AppHostHttpListenerBase appHost = new my.HttpApi.myApiServiceHostBase("My Service", "my.ApiService");   


           string listeningURL = "http://localhost:8081/";

            var appSettings = new ServiceStack.Configuration.AppSettings();
            my.HttpApi.FakeProvider.ProductProvider.Init(appSettings);
            my.HttpApi.FakeProvider.UserProvider.Init(appSettings);

#if DEBUG

            try
            {
                appHost.Init();
                appHost.Start(listeningURL);

                Console.WriteLine("Press <CTRL>+C to stop.");
                Thread.Sleep(Timeout.Infinite);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
                throw;
            }
            finally
            {
                appHost.Stop();
            }

            Console.WriteLine("WinServiceAppHost has finished");

configure method :

public override void Configure(Funq.Container container)
        {
            Plugins.RemoveAll(x => x is CsvFormat);
            Plugins.RemoveAll(x => x is HtmlFormat);

            ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

            //register any dependencies your services use, e.g:
            //container.Register<ICacheClient>(new MemoryCacheClient());

            var config = new EndpointHostConfig { DefaultContentType = ContentType.Json, ServiceStackHandlerFactoryPath = "api" };


            SetConfig(config);
            Plugins.Add(new ServiceStack.Api.Swagger.SwaggerFeature());

            Dictionary<Type, string[]> serviceRoutes = new Dictionary<Type, string[]>();
            serviceRoutes.Add(typeof(AuthService), new[] { "/auth/user" });


            AuthFeature authFeature = new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new FakeCredentialsAuthProvider() });
            authFeature.IncludeAssignRoleServices = false;
            authFeature.ServiceRoutes = serviceRoutes;                      //specify manual auth routes        

            Plugins.Add(authFeature);

            container.Register<ICacheClient>(new MemoryCacheClient());
            var userRep = new InMemoryAuthRepository();
            container.Register<IUserAuthRepository>(userRep);

            Plugins.Add(new CorsFeature(allowedOrigins: "*",
                        allowedMethods: "GET, POST, OPTIONS",
                        //allowedHeaders: "Content-Type",
                        allowedHeaders : "Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date, Content-Type, X-Atmosphere-Transport,  *",
                        allowCredentials: false));
}

Update 2 :

1.) Removed the plugins sections above that is removing html and csv

2.) Ran the following in the package manager (nuget) :

Install-Package ServiceStack.Api.Swagger

still no handler found.

The advice in this question ( ServiceStack: No /swagger-ui/index.html ) that marfarma pointed me at suggests I may not have the 'swagger-ui' html and javascript present. I do.

It appears the self hosted servicestack only 'handles' the specified routes, and when I ask the self hosted service to deliver the swagger html and javascript, I get the "handler for request not found" error above.

When I visit the /resources address in my self hosted service, it shows the expected page and data (suggesting the swagger plugin is doing its thing properly), but when I load up the swagger html and javascript from the file system (not 'served' by my service), and provide it the resource url that works, I get "Can't read from server. It may not have the appropriate access-control-origin settings.", which appears to be a CORS issue, but I've enabled cors on my service (it appears an issue with the Swagger UI code), the swagger-ui send my self hosted service a request sent as 'OPTIONS' (instead of GET or POST), and the options request fails :(

1条回答
趁早两清
2楼-- · 2019-05-17 17:48

as answered in Swagger not working on a self hosted ServiceStack Service:

self hosted services are serving files from bin/debug -> copy always or copy if newer is needed.

查看更多
登录 后发表回答