Swagger-Akka-Http brings Swagger support for Akka-Http Apis. The included SwaggerHttpService
route will inspect Scala types with Swagger annotations and build a swagger compliant endpoint for a swagger compliant ui.
This project was featured in a blog entry on codecentric.
There is another blog entry and demo hosted by Knoldus.
This is a fork of gettyimages/spray-swagger which has been extended to include pull requests to support the latest swagger.io annotations. swagger-spray/swagger-spray is an actively maintained Spray equivalent.
The swagger spec is helpful for understanding the swagger api and resource declaration semantics behind swagger-core annotations.
The jars are hosted on sonatype and mirrored to Maven Central. Swagger-akka-http is built against scala 2.11 and 2.12. Snapshot releases are also hosted on sonatype.
Version | Stability | Branch | Description |
---|---|---|---|
2.0.0 | beta | master | Supports Swagger 2.0.X and OpenAPI 3.0 Specification. Still regarded as expermental. |
1.0.0 | stable | swagger-1.5 | Supports Swagger 1.5.X and Swagger 2.0 Specification. |
libraryDependencies += "com.github.swagger-akka-http" %% "swagger-akka-http" % "1.0.0"
swagger-akka-http 0.10.x and 0.11.x both have had some changes in APIs, for those who are upgrading. See below for details.
Swagger libraries depend heavily on Jackson. If you need to older versions of Jackson, consider using swagger-akka-http 0.8.2. It depends on Jackson 2.4.
Scala 2.10 support for akka-http 2.0.3 requires swagger-akka-http 0.6.2.
pjfanning/swagger-akka-http-sample is a simple sample using this project.
pjfanning/swagger-akka-http-sample-java demonstrates the experimental Java DSL support in swagger-akka-http 0.10.1.
The /test
directory includes an HttpSwaggerServiceSpec
which uses akka-http-testkit
to test the API. It uses a PetHttpService
and UserHttpService
declared in the /samples
folder.
The SwaggerHttpService
is a trait extending Akka-Http's HttpService
. It will generate the appropriate Swagger json schema based on a set of inputs declaring your Api and the types you want to expose.
The SwaggerHttpService
contains a routes
property you can concatenate along with your existing akka-http routes. This will expose an endpoint at <baseUrl>/<specPath>/<resourcePath>
with the specified apiVersion
, swaggerVersion
and resource listing.
The service requires a set of apiTypes
and modelTypes
you want to expose via Swagger. These types include the appropriate Swagger annotations for describing your api. The SwaggerHttpService
will inspect these annotations and build the appropriate Swagger response.
Here's an example SwaggerHttpService
snippet which exposes Swagger's PetStore resources, Pet
, User
and Store
. The routes property can be concatenated to your other route definitions:
object SwaggerDocService extends SwaggerHttpService {
override val apiClasses: Set[Class[_]] = Set(classOf[PetService], classOf[UserService], classOf[StoreService])
override val host = "localhost:8080" //the url of your api, not swagger's json endpoint
override val basePath = "/" //the basePath for the API you are exposing
override val apiDocsPath = "api-docs" //where you want the swagger-json endpoint exposed
override val info = Info() //provides license and other description details
}.routes
This (experimental) support is added in swagger-akka-http 0.10.1. See pjfanning/swagger-akka-http-sample-java for a demo application.
import com.github.swagger.akka.javadsl.SwaggerGenerator;
class MySwaggerGenerator extends SwaggerGenerator {
@Override
public Set<Class<?>> apiClasses() {
return Collections.singleton(PetService.class);
}
@Override
public String host() {
return "localhost:8080"; //the url of your api, not swagger's json endpoint
}
@Override
public String basePath() {
return "/"; //the basePath for the API you are exposing
}
@Override
public String apiDocsPath() {
return "api-docs"; //where you want the swagger-json endpoint exposed
}
@Override
public Info info() {
return new io.swagger.models.Info(); //provides license and other description details
}
}
In versions prior to 0.10.0, you needed to use code like this:
class SwaggerDocService(system: ActorSystem) extends SwaggerHttpService with HasActorSystem {
override implicit val actorSystem: ActorSystem = system
override implicit val materializer: ActorMaterializer = ActorMaterializer()
override val apiTypes = Seq(typeOf[PetService], typeOf[UserService], typeOf[StoreService])
override val host = "localhost:8080" //the url of your api, not swagger's json endpoint
override val basePath = "/" //the basePath for the API you are exposing
override val apiDocsPath = "api-docs" //where you want the swagger-json endpoint exposed
override val info = Info() //provides license and other description details
}.routes
- 0.10.0 drops HasActorSystem trait that was not actually useful
- apiClasses has replaced apiTypes
- In Scala 2.11, you will need to explicitly use the
Set[Class[_]]
type, while Scala 2.12 seems to be able to infer it
- In Scala 2.11, you will need to explicitly use the
SwaggerHttpService
now usesdef
s instead ofval
s for more flexibility
The val scheme = Scheme.HTTP
has been replaced with val schemes = List(Scheme.HTTP)
Akka-Http routing works by concatenating various routes, built up by directives, to produce an api. The routing dsl is an elegant way to describe an api and differs from the more common class and method approach of other frameworks. But because Swagger's annotation library requires classes, methods and fields to describe an Api, one may find it difficult to annotate a akka-http routing application.
A simple solution is to break apart a akka-http routing application into various resource traits, with methods for specific api operations, joined by route concatentation into a route property. These traits with can then be joined together by their own route properties into a complete api. Despite losing the completeness of an entire api the result is a more modular application with a succint resource list. The balance is up to the developer but for a reasonably-sized applicaiton organizing routes across various traits is probably a good idea.
With this structure you can apply @Api
annotations to these individual traits and @ApiOperation
annotations to methods.
You can also use jax-rs @Path
annotations alongside @ApiOperation
s if you need fine-grained control over path specifications or if you want to support multiple paths per operation. The functionality is the same as swagger-core.
The general pattern for resource definitions and akka-http routes:
- Place an individual resource in its own trait
- Annotate the trait with
@Api
to describe the resource - Define specific api operations with
def
methods which produce a route - Annotate these methods with
@ApiOperation
,@ApiImplictParams
and@ApiResponse
accordingly - Concatenate operations together into a single routes property, wrapped with a path directive for that resource
- Concatenate all resource traits together on their routes property to produce the final route structure for your application.
Here's what Swagger's pet resource would look like:
@Api(value = "/pet", description = "Operations about pets")
trait PetHttpService extends HttpService {
@ApiOperation(httpMethod = "GET", response = classOf[Pet], value = "Returns a pet based on ID")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "petId", required = false, dataType = "integer", paramType = "path", value = "ID of pet that needs to be fetched")
))
@ApiResponses(Array(
new ApiResponse(code = 400, message = "Invalid ID Supplied"),
new ApiResponse(code = 404, message = "Pet not found")))
def petGetRoute = get { path("pet" / IntNumber) { petId =>
complete(s"Hello, I'm pet ${petId}!")
} }
}
Notice the use of ApiImplicitParams
. This is the best way to apply parameter information. The paramType
can be used to specify path
, body
, header
, query
or form
. If the dataType value is not of the basic types, swagger-akka-http
will try and find the type in the modelTypes
sequence. Refer to swagger-core for other attribute information.
Model definitions are fairly self-explanatory. Attributes are applied to case class entities and their respective properties. A simplified Pet model:
@ApiModel(description = "A pet object")
case class Pet(
@(ApiModelProperty @field)(value = "unique identifier for the pet")
val id: Int,
@(ApiModelProperty @field)(value = "The name of the pet")
val name: String)
This library does not include Swagger's UI only the api support for powering a UI. Adding such a UI to your akka-http app is easy with akka-http's getFromResource
and getFromResourceDirectory
support.
To add a Swagger UI to your site, simply drop the static site files into the resources directory of your project. The following trait will expose a swagger
route hosting files from the resources/swagger/
directory:
trait Site extends Directives {
val site =
path("swagger") { getFromResource("swagger/index.html") } ~
getFromResourceDirectory("swagger")
}
You can then mix this trait with a new or existing Akka-Http class with an actorRefFactory
and concatenate the site
route value to your existing route definitions.