Swagger with WebApi and OWIn - asp.net-web-api

I want to use Swagger to document my api based on .Net WebApi and Owin for OAuth.
I use the Swashbuckle.Core Nuget Package and I configure swagger in my startup class:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
IContainer container = AutoFacConfig.Register(config, app);
app.UseCors(CorsOptions.AllowAll);
ConfigureOAuth(app, container);
WebApiConfig.Register(config);
AutoMapperConfig.Register();
config
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "My API");
c.IncludeXmlComments(GetXmlCommentsPath());
})
.EnableSwaggerUi();
app.UseWebApi(config);
}
This is my GetXmlCommentsPath Method
protected static string GetXmlCommentsPath()
{
return System.String.Format(#"{0}\bin\My.WebApplication.XML", System.AppDomain.CurrentDomain.BaseDirectory);
}
If now I start my app I recive a StackOverFlowException and the Swagger Website told's me
Can't read from server. It may not have the appropriate access-control-origin settings.
What I do wrong?

Related

Spring Cloud APIGW, Spring Boot and OpenAPI issue - CORS issue

I am using Spring Boot and Microservices stack using Spring Cloud APIGW. I am using the same code mentioned here: https://piotrminkowski.com/2020/02/20/microservices-api-documentation-with-springdoc-openapi/
When I hit any endpoint, I don't see response is coming and getting below error.
Access to fetch at 'http://192.168.0.2:49382/' from origin 'http://localhost:8060' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Source code: https://github.com/piomin/sample-spring-microservices-new
I was able to fix it by myself looking at suggestion here: Spring Cloud Gateway and Springdoc OpenAPi integration and https://github.com/springdoc/springdoc-openapi/issues/1144
I had to add below in apigw-service in application.properties file
server:
forward-headers-strategy: framework
Also, in each microservice, you need to add below bean
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
You should add swagger configuration
#Configuration
#OpenAPIDefinition(servers = {
#Server(url = "/", description = "Default Server URL")
})
public class SwaggerConfiguration {
#Bean
public OpenAPI customOpenAPI(#Value("springdoc-openapi-ui") String serviceTitle, #Value("1.6.12") String serviceVersion) {
final String securitySchemeName = "bearerAuth";
return new OpenAPI()
.components(
new Components().addSecuritySchemes(
securitySchemeName,
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
)
)
.security(List.of(new SecurityRequirement().addList(securitySchemeName)))
.info(new Info().title(serviceTitle).version(serviceVersion));
}
}

Spring Boot - I have configured HTTPS using Self Sign Certificate and running properly on HTTPS. But I want to configure HTTP for API rest on HTTPS?

//Createing tomcat server object
#Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint()
securityConstraint.setUserConstraint(USER_CONSTRAINT)
SecurityCollection collection = new SecurityCollection()
collection.addPattern("/*")
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}
//Here is a redirec connector
private Connector redirectConnector() {
Connector connector = new Connector(
TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme(HTTP);
connector.setPort(HTTP_PORT); -//This is port of http but not working
connector.setSecure(false);
connector.setRedirectPort(HTTPS_PORT); //This is working
return connector;
}
//At last my requirement is to fetch application on Https and API using swagger on http.

Adding authorization to Annotation-driven swagger.json with Jersey 2 and Spring Boot

I'm trying to add Basic Authentication to Swagger UI for a to a Swagger-annotated Jersey 2.0 web service built with Spring Boot. I'm using:
Spring Boot 1.5.4
spring-boot-starter-jersey
Swagger UI 3.0.4
(Maven package) swagger-jersey2-jaxrs 1.5.13
I'm able to generate a swagger.json file with the following JerseyConfig and with Swagger annotations on my Resources. This article was immensely helpful in getting this far.
#Component
public class JerseyConfiguration extends ResourceConfig {
private static Log logger = LogFactory.getLog(JerseyConfiguration.class);
#Value("${spring.jersey.application-path:/}")
private String apiPath;
public JerseyConfiguration() {
registerEndpoints();
configureSwagger();
}
private void registerEndpoints() {
register(MyEndpoints.class);
// Generate Jersey WADL at /<Jersey's servlet path>/application.wadl
register(WadlResource.class);
// Lets us get to static content like swagger
property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, "((/swagger/.*)|(.*\\.html))");
}
/**
* Configure the Swagger documentation for this API.
*/
private void configureSwagger() {
// Creates file at localhost:port/swagger.json
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
BeanConfig config = new BeanConfig();
config.setConfigId("example-jersey-app");
config.setTitle("Spring Boot + Jersey + Swagger");
config.setVersion("2");
config.setContact("Me <me#example.com>");
config.setSchemes(new String[] {"http", "https"});
config.setResourcePackage("com.example.api");
config.setBasePath(this.apiPath);
config.setPrettyPrint(true);
config.setScan(true);
}
}
Now I want to be able to use Basic Authentication to connect to these services from Swagger UI. I've configured it in Spring and can use it to authenticate to the site, but not from Swagger UI.
Unfortunately, none of the Spring Boot examples currently on the Swagger sample site include Jersey and authentication, and none of the Jersey examples use Spring Boot and #SpringBootApplication like I'm using on in my project.
How do I get Basic Auth to show up in the Swagger UI?
I was able to get this to work by adding ServletConfigAware to JerseyConfiguration. Then I could use the same style of Swagger configuration used in the Swagger Bootstrap.java examples.
#Component
public class JerseyConfiguration extends ResourceConfig implements ServletConfigAware{
private ServletConfig servletConfig;
// ... this is all unchanged ...
/**
* Configure the Swagger documentation for this API.
*/
private void configureSwagger() {
// Creates file at localhost:port/swagger.json
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
BeanConfig config = new BeanConfig();
// ... this is all unchanged ...
config.setScan(true);
Swagger swagger = new Swagger();
swagger.securityDefinition("basicAuth", new BasicAuthDefinition());
new SwaggerContextService().withServletConfig(servletConfig).updateSwagger(swagger);
}
#Override
public void setServletConfig(ServletConfig servletConfig) {
logger.info("Setting ServletConfig");
this.servletConfig = servletConfig;
}
}
After making these changes, and adding annotations like the following to my endpoints:
#Api(value = "/api", description = "My super API",
authorizations = {#Authorization(value="basicAuth")})
#Path("api")
#Component
public class MyApi {
I saw the following changes:
Added to my swagger.json:
"securityDefinitions":{"basicAuth":{"type":"basic"}}
...
"security":[{"basicAuth":[]}]}}
Also, in Swagger UI, a new green button appeared in the same row as the Schemes dropdown, that says "Authorize" with an open lock on it. If I click on it, a popup shows up where I can enter the username and password. Now those credentials are sent to the API when I use the Swagger UI "Try It" feature.

How to specify my restful API for swagger-ui in spring-boot application

I am using spring-boot + jersey as restful implementation. I have setup the swagger and I am able to open the swagger ui on the browser. But the swagger-ui doesn't have any API to show, it is an empty page. Below is the code I setup for configuring swagger. How can I let swagger to scan my API definition in jersey?
SwaggerConfiguration.java
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/com.hello.*"))
.build().pathMapping("/swagger2");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("App API")
.description("App API")
.version("1.0.0-SNAPSHOT")
.termsOfServiceUrl("")
.contact("Cooltoo company")
.license("Public")
.licenseUrl("http://hello.com/")
.build();
}
JerseyConfiguration.java
#Configuration
#EnableSwagger2
#EnableAutoConfiguration
#Api(value = "home", description = "Demo API")
#ApplicationPath("/nursego")
public class JerseyConfiguration extends ResourceConfig {
public JerseyConfiguration() {
register(BadgeAPI.class);
register(MultiPartFeature.class);
register(OrderAPI.class);
register(NurseAPI.class);
configureSwagger();
}
private void configureSwagger() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/nursego");
beanConfig.setResourcePackage("com.cooltoo.backend.api");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
register( io.swagger.jaxrs.listing.ApiListingResource.class );
register( io.swagger.jaxrs.listing.SwaggerSerializers.class );
}
}
When I open http://localhost:8080/swagger-ui.html, I see below image but none of them are from my API. I don't know where they are from
I used the BeanConfig class to embed the Swagger into my SpringBoot+Jersey implmentation, the code example is as follows,
#Component
#ApplicationPath( "/api" )
public class JerseyConfig extends ResourceConfig{
public JerseyConfig(){
// method for embedding the Swagger
configSwagger();
// registers the REST resource classes
configEndPoints();
}
private void configEndPoints(){
// here register all the REST resource classes
}
private void configSwagger(){
BeanConfig beanConfig = new BeanConfig();
beanConfig.setSchemes( new String[]{ "http" } );
beanConfig.setHost( "localhost:9001" );
beanConfig.setBasePath( "/api" );
beanConfig.setDescription( "REST API services for accessing the pcg application" );
beanConfig.setTitle( "RESTAPI" );
beanConfig.setVersion( "1.0.1" );
// this will tell Swagger config to scan only these packages
beanConfig.setResourcePackage( "com.aig.rest.web" );
beanConfig.setScan( true );
register( io.swagger.jaxrs.listing.ApiListingResource.class );
register( io.swagger.jaxrs.listing.SwaggerSerializers.class );
}
}
I believe #EnableSwagger2 annotation works if the endpoints are implemented using Spring MVC instead of Jersey (or any other JAX-RS impl).
I have detailed how to accomplish this in a blog post I created earlier this year, Microservices using Spring Boot, Jersey Swagger and Docker
Basically if you need to document your Jersey-implemented endpoints via Swagger, you would need to:
1)
Make sure your Spring Boot app scans for components located in specific packages (ie com.asimio.jerseyexample.config) via:
#SpringBootApplication(
scanBasePackages = {
"com.asimio.jerseyexample.config", "com.asimio.jerseyexample.rest"
}
)
2) Jersey configuration class implementation:
package com.asimio.jerseyexample.config;
...
#Component
public class JerseyConfig extends ResourceConfig {
#Value("${spring.jersey.application-path:/}")
private String apiPath;
public JerseyConfig() {
// Register endpoints, providers, ...
this.registerEndpoints();
}
#PostConstruct
public void init() {
// Register components where DI is needed
this.configureSwagger();
}
private void registerEndpoints() {
this.register(HelloResource.class);
// Access through /<Jersey's servlet path>/application.wadl
this.register(WadlResource.class);
}
private void configureSwagger() {
// Available at localhost:port/swagger.json
this.register(ApiListingResource.class);
this.register(SwaggerSerializers.class);
BeanConfig config = new BeanConfig();
config.setConfigId("springboot-jersey-swagger-docker-example");
config.setTitle("Spring Boot + Jersey + Swagger + Docker Example");
config.setVersion("v1");
config.setContact("Orlando L Otero");
config.setSchemes(new String[] { "http", "https" });
config.setBasePath(this.apiPath);
config.setResourcePackage("com.asimio.jerseyexample.rest.v1");
config.setPrettyPrint(true);
config.setScan(true);
}
}
3) Resource implementation using JAX-RS (Jersey) and Swagger annotations:
package com.asimio.jerseyexample.rest.v1;
...
#Component
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Api(value = "Hello resource", produces = "application/json")
public class HelloResource {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloResource.class);
#GET
#Path("v1/hello/{name}")
#ApiOperation(value = "Gets a hello resource. Version 1 - (version in URL)", response = Hello.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Hello resource found"),
#ApiResponse(code = 404, message = "Hello resource not found")
})
public Response getHelloVersionInUrl(#ApiParam #PathParam("name") String name) {
LOGGER.info("getHelloVersionInUrl() v1");
return this.getHello(name, "Version 1 - passed in URL");
}
...
}
4) Make sure your app's Spring Boot configuration file makes a distinction between Spring MVC (for actuator endpoints) and Jersey (for resources) endpoints:
application.yml
...
# Spring MVC dispatcher servlet path. Needs to be different than Jersey's to enable/disable Actuator endpoints access (/info, /health, ...)
server.servlet-path: /
# Jersey dispatcher servlet
spring.jersey.application-path: /api
...

Cannot resolve symbol ExternalServiceResource while registering http client to jersey environment in Dropwizard Application

Iam implementing Dropwizard client in a Dropwizard REST Application.
I am following their User Manual.
While trying to register the client to jersey environment but cannot find the class ExternalServiceResource
#Override
public void run(ExampleConfiguration config,
Environment environment) {
final HttpClient httpClient = new HttpClientBuilder(environment).using(config.getHttpClientConfiguration())
.build();
environment.jersey().register(new ExternalServiceResource(httpClient));
}
I think that ExternalServiceResource was an example but it would look like:
#Path("/your/path")
public class ExternalServiceResource {
private final HttpClient client;
public ExternalServiceResource(HttpClient client) {
this.client = client;
}
#GET
public String doStuff() {
return /* use client to make some call */;
}
}
You can put whatever name you want. The only requirement to create a resource is the #Path annotation, that you must put at class level, and some methods #GET, #POST...

Resources