[scala] fix akka-scala-client template compilation warnings (#5106)

* fix akka-scala-client template compilation warnings

add COOKIE location authorization key
regenerate template

* fix scala akka-http client model imports

* fix #4004 custom package name in reference.conf

* fix scaka-akka codegen test
This commit is contained in:
Aleksandr Nekrasov 2020-02-06 21:15:43 +07:00 committed by GitHub
parent 8779fc6485
commit 1bba3a563e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 202 additions and 104 deletions

View File

@ -150,12 +150,13 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("mainPackage")) { if (additionalProperties.containsKey("mainPackage")) {
setMainPackage((String) additionalProperties.get("mainPackage")); setMainPackage((String) additionalProperties.get("mainPackage"));
additionalProperties.replace("configKeyPath", this.configKeyPath);
apiPackage = mainPackage + ".api"; apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model"; modelPackage = mainPackage + ".model";
invokerPackage = mainPackage + ".core"; invokerPackage = mainPackage + ".core";
additionalProperties.put("apiPackage", apiPackage); additionalProperties.put("apiPackage", apiPackage);
additionalProperties.put("modelPackage", apiPackage); additionalProperties.put("modelPackage", modelPackage);
additionalProperties.put("invokerPackage", apiPackage); additionalProperties.put("invokerPackage", invokerPackage);
} }
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@ -366,6 +367,6 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
} }
public void setMainPackage(String mainPackage) { public void setMainPackage(String mainPackage) {
this.mainPackage = mainPackage; this.configKeyPath = this.mainPackage = mainPackage;
} }
} }

View File

@ -22,7 +22,7 @@ class {{classname}}(baseUrl: String) {
{{/javadocRenderer}} {{/javadocRenderer}}
def {{operationId}}({{>methodParameters}}): ApiRequest[{{>operationReturnType}}] = def {{operationId}}({{>methodParameters}}): ApiRequest[{{>operationReturnType}}] =
ApiRequest[{{>operationReturnType}}](ApiMethods.{{httpMethod.toUpperCase}}, baseUrl, "{{{path}}}", {{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}}{{^consumes}}"application/json"{{/consumes}}) ApiRequest[{{>operationReturnType}}](ApiMethods.{{httpMethod.toUpperCase}}, baseUrl, "{{{path}}}", {{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}}{{^consumes}}"application/json"{{/consumes}})
{{#authMethods}}{{#isApiKey}}.withApiKey(apiKey, "{{keyParamName}}", {{#isKeyInQuery}}QUERY{{/isKeyInQuery}}{{#isKeyInHeader}}HEADER{{/isKeyInHeader}}) {{#authMethods}}{{#isApiKey}}.withApiKey(apiKey, "{{keyParamName}}", {{#isKeyInQuery}}QUERY{{/isKeyInQuery}}{{#isKeyInHeader}}HEADER{{/isKeyInHeader}}{{#isKeyInCookie}}COOKIE{{/isKeyInCookie}})
{{/isApiKey}}{{#isBasic}}.withCredentials(basicAuth) {{/isApiKey}}{{#isBasic}}.withCredentials(basicAuth)
{{/isBasic}}{{/authMethods}}{{#bodyParam}}.withBody({{paramName}}) {{/isBasic}}{{/authMethods}}{{#bodyParam}}.withBody({{paramName}})
{{/bodyParam}}{{#formParams}}.withFormParam({{>paramCreation}}) {{/bodyParam}}{{#formParams}}.withFormParam({{>paramCreation}})

View File

@ -45,7 +45,7 @@ object ApiInvoker {
* *
* @param request the apiRequest to be executed * @param request the apiRequest to be executed
*/ */
implicit class ApiRequestImprovements[T](request: ApiRequest[T]) { implicit class ApiRequestImprovements[T: Manifest](request: ApiRequest[T]) {
def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] = def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] =
response(ec, system, invoker) response(ec, system, invoker)
@ -67,7 +67,7 @@ object ApiInvoker {
def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET) def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET)
} }
case object DateTimeSerializer extends CustomSerializer[DateTime](format => ( { case object DateTimeSerializer extends CustomSerializer[DateTime](_ => ( {
case JString(s) => case JString(s) =>
ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s) ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s)
}, { }, {
@ -215,7 +215,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
Uri(r.basePath + opPathWithParams).withQuery(query) Uri(r.basePath + opPathWithParams).withQuery(query)
} }
def execute[T](r: ApiRequest[T]): Future[ApiResponse[T]] = { def execute[T: Manifest](r: ApiRequest[T]): Future[ApiResponse[T]] = {
implicit val timeout: Timeout = settings.connectionTimeout implicit val timeout: Timeout = settings.connectionTimeout
val request = createRequest(makeUri(r), r) val request = createRequest(makeUri(r), r)
@ -239,8 +239,8 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
.flatMap(unmarshallApiResponse(r)) .flatMap(unmarshallApiResponse(r))
} }
def unmarshallApiResponse[T](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = { def unmarshallApiResponse[T: Manifest](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
def responseForState[V](state: ResponseState, value: V) = { def responseForState[V](state: ResponseState, value: V): ApiResponse[V] = {
state match { state match {
case ResponseState.Success => case ResponseState.Success =>
ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap) ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
@ -253,31 +253,29 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
) )
} }
} }
val mf = implicitly(manifest[T])
request request
.responseForCode(response.status.intValue) .responseForCode(response.status.intValue) match {
.map { case Some((Manifest.Unit, state: ResponseState)) =>
case (Manifest.Unit, state: ResponseState) => Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]])
// FIXME Casting is ugly, how to do better? case Some((manifest, state: ResponseState)) if manifest == mf =>
Future(responseForState(state, Unit)).asInstanceOf[Future[ApiResponse[T]]] implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
case (manifest: Manifest[T], state: ResponseState) =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](manifest, serialization, formats)
Unmarshal(response.entity) Unmarshal(response.entity)
.to[T] .to[T]
.recoverWith { .recoverWith {
case e ⇒ throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e) case e ⇒ throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
} }
.map(value => responseForState(state, value)) .map(value => responseForState(state, value))
case None | Some(_) =>
Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString)))
} }
.getOrElse(Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString))))
} }
} }
sealed trait CustomContentTypes { sealed trait CustomContentTypes {
protected def normalizedContentType(original: String): ContentType = protected def normalizedContentType(original: String): ContentType =
ContentType(MediaTypes.forExtension(original), () => HttpCharsets.`UTF-8`) ContentType(parseContentType(original).mediaType, () => HttpCharsets.`UTF-8`)
protected def parseContentType(contentType: String): ContentType = { protected def parseContentType(contentType: String): ContentType = {

View File

@ -1,9 +1,10 @@
{{>licenseInfo}} {{>licenseInfo}}
package {{package}} package {{package}}
{{#imports}}
import {{import}}
{{/imports}}
import {{mainPackage}}.core.ApiModel import {{mainPackage}}.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
{{#models}} {{#models}}
{{#model}} {{#model}}

View File

@ -85,6 +85,8 @@ object ApiKeyLocations {
case object HEADER extends ApiKeyLocation case object HEADER extends ApiKeyLocation
case object COOKIE extends ApiKeyLocation
} }

View File

@ -26,6 +26,15 @@ paths:
description: '' description: ''
operationId: addPet operationId: addPet
responses: responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405': '405':
description: Invalid input description: Invalid input
security: security:
@ -41,6 +50,15 @@ paths:
description: '' description: ''
operationId: updatePet operationId: updatePet
responses: responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400': '400':
description: Invalid ID supplied description: Invalid ID supplied
'404': '404':

View File

@ -11,9 +11,8 @@
*/ */
package hello.world.model package hello.world.model
import hello.world.core.ApiModel
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.UUID import hello.world.core.ApiModel
case class SomeObj ( case class SomeObj (
`type`: Option[SomeObjEnums.`Type`] = None, `type`: Option[SomeObjEnums.`Type`] = None,

View File

@ -91,6 +91,8 @@ Class | Method | HTTP request | Description
- [ApiResponse](ApiResponse.md) - [ApiResponse](ApiResponse.md)
- [Category](Category.md) - [Category](Category.md)
- [InlineObject](InlineObject.md)
- [InlineObject1](InlineObject1.md)
- [Order](Order.md) - [Order](Order.md)
- [Pet](Pet.md) - [Pet](Pet.md)
- [Tag](Tag.md) - [Tag](Tag.md)
@ -106,6 +108,12 @@ Authentication schemes defined for the API:
- **API key parameter name**: api_key - **API key parameter name**: api_key
- **Location**: HTTP header - **Location**: HTTP header
### auth_cookie
- **Type**: API key
- **API key parameter name**: AUTH_KEY
- **Location**:
## Author ## Author

View File

@ -1 +1 @@
sbt.version=1.2.8 sbt.version=1.3.6

View File

@ -27,13 +27,15 @@ class PetApi(baseUrl: String) {
/** /**
* Expected answers: * Expected answers:
* code 200 : Pet (successful operation)
* code 405 : (Invalid input) * code 405 : (Invalid input)
* *
* @param body Pet object that needs to be added to the store * @param pet Pet object that needs to be added to the store
*/ */
def addPet(body: Pet): ApiRequest[Unit] = def addPet(pet: Pet): ApiRequest[Pet] =
ApiRequest[Unit](ApiMethods.POST, baseUrl, "/pet", "application/json") ApiRequest[Pet](ApiMethods.POST, baseUrl, "/pet", "application/json")
.withBody(body) .withBody(pet)
.withSuccessResponse[Pet](200)
.withErrorResponse[Unit](405) .withErrorResponse[Unit](405)
@ -107,15 +109,17 @@ class PetApi(baseUrl: String) {
/** /**
* Expected answers: * Expected answers:
* code 200 : Pet (successful operation)
* code 400 : (Invalid ID supplied) * code 400 : (Invalid ID supplied)
* code 404 : (Pet not found) * code 404 : (Pet not found)
* code 405 : (Validation exception) * code 405 : (Validation exception)
* *
* @param body Pet object that needs to be added to the store * @param pet Pet object that needs to be added to the store
*/ */
def updatePet(body: Pet): ApiRequest[Unit] = def updatePet(pet: Pet): ApiRequest[Pet] =
ApiRequest[Unit](ApiMethods.PUT, baseUrl, "/pet", "application/json") ApiRequest[Pet](ApiMethods.PUT, baseUrl, "/pet", "application/json")
.withBody(body) .withBody(pet)
.withSuccessResponse[Pet](200)
.withErrorResponse[Unit](400) .withErrorResponse[Unit](400)
.withErrorResponse[Unit](404) .withErrorResponse[Unit](404)
.withErrorResponse[Unit](405) .withErrorResponse[Unit](405)

View File

@ -77,11 +77,11 @@ class StoreApi(baseUrl: String) {
* code 200 : Order (successful operation) * code 200 : Order (successful operation)
* code 400 : (Invalid Order) * code 400 : (Invalid Order)
* *
* @param body order placed for purchasing the pet * @param order order placed for purchasing the pet
*/ */
def placeOrder(body: Order): ApiRequest[Order] = def placeOrder(order: Order): ApiRequest[Order] =
ApiRequest[Order](ApiMethods.POST, baseUrl, "/store/order", "application/json") ApiRequest[Order](ApiMethods.POST, baseUrl, "/store/order", "application/json")
.withBody(body) .withBody(order)
.withSuccessResponse[Order](200) .withSuccessResponse[Order](200)
.withErrorResponse[Unit](400) .withErrorResponse[Unit](400)

View File

@ -29,11 +29,15 @@ class UserApi(baseUrl: String) {
* Expected answers: * Expected answers:
* code 0 : (successful operation) * code 0 : (successful operation)
* *
* @param body Created user object * Available security schemes:
* auth_cookie (apiKey)
*
* @param user Created user object
*/ */
def createUser(body: User): ApiRequest[Unit] = def createUser(user: User)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user", "application/json") ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user", "application/json")
.withBody(body) .withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit] .withDefaultSuccessResponse[Unit]
@ -41,11 +45,15 @@ class UserApi(baseUrl: String) {
* Expected answers: * Expected answers:
* code 0 : (successful operation) * code 0 : (successful operation)
* *
* @param body List of user object * Available security schemes:
* auth_cookie (apiKey)
*
* @param user List of user object
*/ */
def createUsersWithArrayInput(body: Seq[User]): ApiRequest[Unit] = def createUsersWithArrayInput(user: Seq[User])(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithArray", "application/json") ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithArray", "application/json")
.withBody(body) .withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit] .withDefaultSuccessResponse[Unit]
@ -53,11 +61,15 @@ class UserApi(baseUrl: String) {
* Expected answers: * Expected answers:
* code 0 : (successful operation) * code 0 : (successful operation)
* *
* @param body List of user object * Available security schemes:
* auth_cookie (apiKey)
*
* @param user List of user object
*/ */
def createUsersWithListInput(body: Seq[User]): ApiRequest[Unit] = def createUsersWithListInput(user: Seq[User])(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithList", "application/json") ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithList", "application/json")
.withBody(body) .withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit] .withDefaultSuccessResponse[Unit]
@ -68,10 +80,14 @@ class UserApi(baseUrl: String) {
* code 400 : (Invalid username supplied) * code 400 : (Invalid username supplied)
* code 404 : (User not found) * code 404 : (User not found)
* *
* Available security schemes:
* auth_cookie (apiKey)
*
* @param username The name that needs to be deleted * @param username The name that needs to be deleted
*/ */
def deleteUser(username: String): ApiRequest[Unit] = def deleteUser(username: String)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.DELETE, baseUrl, "/user/{username}", "application/json") ApiRequest[Unit](ApiMethods.DELETE, baseUrl, "/user/{username}", "application/json")
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withPathParam("username", username) .withPathParam("username", username)
.withErrorResponse[Unit](400) .withErrorResponse[Unit](400)
.withErrorResponse[Unit](404) .withErrorResponse[Unit](404)
@ -97,6 +113,7 @@ class UserApi(baseUrl: String) {
* Expected answers: * Expected answers:
* code 200 : String (successful operation) * code 200 : String (successful operation)
* Headers : * Headers :
* Set-Cookie - Cookie authentication key for use with the `auth_cookie` apiKey authentication.
* X-Rate-Limit - calls per hour allowed by the user * X-Rate-Limit - calls per hour allowed by the user
* X-Expires-After - date in UTC when toekn expires * X-Expires-After - date in UTC when toekn expires
* code 400 : (Invalid username/password supplied) * code 400 : (Invalid username/password supplied)
@ -112,6 +129,7 @@ class UserApi(baseUrl: String) {
.withErrorResponse[Unit](400) .withErrorResponse[Unit](400)
object LoginUserHeaders { object LoginUserHeaders {
def setCookie(r: ApiReturnWithHeaders) = r.getStringHeader("Set-Cookie")
def xRateLimit(r: ApiReturnWithHeaders) = r.getIntHeader("X-Rate-Limit") def xRateLimit(r: ApiReturnWithHeaders) = r.getIntHeader("X-Rate-Limit")
def xExpiresAfter(r: ApiReturnWithHeaders) = r.getDateTimeHeader("X-Expires-After") def xExpiresAfter(r: ApiReturnWithHeaders) = r.getDateTimeHeader("X-Expires-After")
} }
@ -119,9 +137,13 @@ class UserApi(baseUrl: String) {
/** /**
* Expected answers: * Expected answers:
* code 0 : (successful operation) * code 0 : (successful operation)
*
* Available security schemes:
* auth_cookie (apiKey)
*/ */
def logoutUser(): ApiRequest[Unit] = def logoutUser()(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.GET, baseUrl, "/user/logout", "application/json") ApiRequest[Unit](ApiMethods.GET, baseUrl, "/user/logout", "application/json")
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withDefaultSuccessResponse[Unit] .withDefaultSuccessResponse[Unit]
@ -132,12 +154,16 @@ class UserApi(baseUrl: String) {
* code 400 : (Invalid user supplied) * code 400 : (Invalid user supplied)
* code 404 : (User not found) * code 404 : (User not found)
* *
* Available security schemes:
* auth_cookie (apiKey)
*
* @param username name that need to be deleted * @param username name that need to be deleted
* @param body Updated user object * @param user Updated user object
*/ */
def updateUser(username: String, body: User): ApiRequest[Unit] = def updateUser(username: String, user: User)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
ApiRequest[Unit](ApiMethods.PUT, baseUrl, "/user/{username}", "application/json") ApiRequest[Unit](ApiMethods.PUT, baseUrl, "/user/{username}", "application/json")
.withBody(body) .withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withPathParam("username", username) .withPathParam("username", username)
.withErrorResponse[Unit](400) .withErrorResponse[Unit](400)
.withErrorResponse[Unit](404) .withErrorResponse[Unit](404)

View File

@ -55,7 +55,7 @@ object ApiInvoker {
* *
* @param request the apiRequest to be executed * @param request the apiRequest to be executed
*/ */
implicit class ApiRequestImprovements[T](request: ApiRequest[T]) { implicit class ApiRequestImprovements[T: Manifest](request: ApiRequest[T]) {
def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] = def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] =
response(ec, system, invoker) response(ec, system, invoker)
@ -77,7 +77,7 @@ object ApiInvoker {
def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET) def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET)
} }
case object DateTimeSerializer extends CustomSerializer[DateTime](format => ( { case object DateTimeSerializer extends CustomSerializer[DateTime](_ => ( {
case JString(s) => case JString(s) =>
ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s) ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s)
}, { }, {
@ -225,7 +225,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
Uri(r.basePath + opPathWithParams).withQuery(query) Uri(r.basePath + opPathWithParams).withQuery(query)
} }
def execute[T](r: ApiRequest[T]): Future[ApiResponse[T]] = { def execute[T: Manifest](r: ApiRequest[T]): Future[ApiResponse[T]] = {
implicit val timeout: Timeout = settings.connectionTimeout implicit val timeout: Timeout = settings.connectionTimeout
val request = createRequest(makeUri(r), r) val request = createRequest(makeUri(r), r)
@ -249,8 +249,8 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
.flatMap(unmarshallApiResponse(r)) .flatMap(unmarshallApiResponse(r))
} }
def unmarshallApiResponse[T](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = { def unmarshallApiResponse[T: Manifest](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
def responseForState[V](state: ResponseState, value: V) = { def responseForState[V](state: ResponseState, value: V): ApiResponse[V] = {
state match { state match {
case ResponseState.Success => case ResponseState.Success =>
ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap) ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
@ -263,31 +263,29 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
) )
} }
} }
val mf = implicitly(manifest[T])
request request
.responseForCode(response.status.intValue) .responseForCode(response.status.intValue) match {
.map { case Some((Manifest.Unit, state: ResponseState)) =>
case (Manifest.Unit, state: ResponseState) => Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]])
// FIXME Casting is ugly, how to do better? case Some((manifest, state: ResponseState)) if manifest == mf =>
Future(responseForState(state, Unit)).asInstanceOf[Future[ApiResponse[T]]] implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
case (manifest: Manifest[T], state: ResponseState) =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](manifest, serialization, formats)
Unmarshal(response.entity) Unmarshal(response.entity)
.to[T] .to[T]
.recoverWith { .recoverWith {
case e throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e) case e throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
} }
.map(value => responseForState(state, value)) .map(value => responseForState(state, value))
case None | Some(_) =>
Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString)))
} }
.getOrElse(Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString))))
} }
} }
sealed trait CustomContentTypes { sealed trait CustomContentTypes {
protected def normalizedContentType(original: String): ContentType = protected def normalizedContentType(original: String): ContentType =
ContentType(MediaTypes.forExtension(original), () => HttpCharsets.`UTF-8`) ContentType(parseContentType(original).mediaType, () => HttpCharsets.`UTF-8`)
protected def parseContentType(contentType: String): ContentType = { protected def parseContentType(contentType: String): ContentType = {

View File

@ -95,6 +95,8 @@ object ApiKeyLocations {
case object HEADER extends ApiKeyLocation case object HEADER extends ApiKeyLocation
case object COOKIE extends ApiKeyLocation
} }

View File

@ -12,8 +12,6 @@
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
case class ApiResponse ( case class ApiResponse (
code: Option[Int] = None, code: Option[Int] = None,

View File

@ -12,8 +12,6 @@
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
case class Category ( case class Category (
id: Option[Long] = None, id: Option[Long] = None,

View File

@ -0,0 +1,23 @@
/**
* OpenAPI Petstore
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
package org.openapitools.client.model
import org.openapitools.client.core.ApiModel
case class InlineObject (
/* Updated name of the pet */
name: Option[String] = None,
/* Updated status of the pet */
status: Option[String] = None
) extends ApiModel

View File

@ -0,0 +1,24 @@
/**
* OpenAPI Petstore
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
package org.openapitools.client.model
import java.io.File
import org.openapitools.client.core.ApiModel
case class InlineObject1 (
/* Additional data to pass to server */
additionalMetadata: Option[String] = None,
/* file to upload */
file: Option[File] = None
) extends ApiModel

View File

@ -11,9 +11,8 @@
*/ */
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.UUID import org.openapitools.client.core.ApiModel
case class Order ( case class Order (
id: Option[Long] = None, id: Option[Long] = None,

View File

@ -12,8 +12,6 @@
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
case class Pet ( case class Pet (
id: Option[Long] = None, id: Option[Long] = None,

View File

@ -12,8 +12,6 @@
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
case class Tag ( case class Tag (
id: Option[Long] = None, id: Option[Long] = None,

View File

@ -12,8 +12,6 @@
package org.openapitools.client.model package org.openapitools.client.model
import org.openapitools.client.core.ApiModel import org.openapitools.client.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
case class User ( case class User (
id: Option[Long] = None, id: Option[Long] = None,

View File

@ -14,8 +14,8 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
private implicit val system: ActorSystem = ActorSystem() private implicit val system: ActorSystem = ActorSystem()
behavior of "PetApi" behavior of "PetApi"
val api = PetApi() val api: PetApi = PetApi()
val invoker = ApiInvoker() val invoker: ApiInvoker = ApiInvoker(EnumsSerializers.all)
private implicit val apiKey: ApiKeyValue = ApiKeyValue("special-key") private implicit val apiKey: ApiKeyValue = ApiKeyValue("special-key")
it should "add and fetch a pet" in { it should "add and fetch a pet" in {
@ -54,7 +54,7 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
} }
it should "update a pet" in { it should "update a pet" in {
val petId = Math.random().toInt val petId = (Math.random()*1000000000).toLong
val createdPet = Pet( val createdPet = Pet(
Some(petId), Some(petId),
Some(Category(Some(1), Some("sold"))), Some(Category(Some(1), Some("sold"))),
@ -65,18 +65,23 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
) )
for { for {
_ <- invoker.execute(api.addPet(createdPet)) createdPet <- invoker.execute(api.addPet(createdPet))
pet: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(petId)) pet: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get))
updatedPet = pet.content.copy(status = Some(PetEnums.Status.Sold)) updatedPet = pet.content.copy(status = Some(PetEnums.Status.Sold), name = "developer")
_ <- invoker.execute(api.updatePet(updatedPet)) updatedPetResponse: core.ApiResponse[Pet] <- invoker.execute(api.updatePet(updatedPet))
updatedRequested <- invoker.execute(api.getPetById(petId)) updatedRequested: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get))
} yield { } yield {
pet.content.name should be("programmer") pet.content.name should be("programmer")
pet.content.status should be(Some(PetEnums.Status.Available)) pet.content.status should be(Some(PetEnums.Status.Available))
updatedRequested.content.name should be("programmer") updatedPetResponse.content.name should be("developer")
updatedPetResponse.content.status should be(Some(PetEnums.Status.Sold))
updatedRequested.content.name should be("developer")
updatedRequested.content.status should be(Some(PetEnums.Status.Sold)) updatedRequested.content.status should be(Some(PetEnums.Status.Sold))
} }
} }
it should "find pets by status" in { it should "find pets by status" in {
@ -90,7 +95,7 @@ class PetApiTest extends AsyncFlatSpec with Matchers {
pets should not be empty pets should not be empty
forAll(pets) { pet => forAll(pets) { pet =>
pet.status should contain("available") pet.status should contain(PetEnums.Status.Available)
} }
} }
} }