Skip to content

Commit

Permalink
[scala] fix akka-scala-client template compilation warnings (#5106)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
chameleon82 authored Feb 6, 2020
1 parent 8779fc6 commit 1bba3a5
Show file tree
Hide file tree
Showing 23 changed files with 202 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,13 @@ public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("mainPackage")) {
setMainPackage((String) additionalProperties.get("mainPackage"));
additionalProperties.replace("configKeyPath", this.configKeyPath);
apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model";
invokerPackage = mainPackage + ".core";
additionalProperties.put("apiPackage", apiPackage);
additionalProperties.put("modelPackage", apiPackage);
additionalProperties.put("invokerPackage", apiPackage);
additionalProperties.put("modelPackage", modelPackage);
additionalProperties.put("invokerPackage", invokerPackage);
}

supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
Expand Down Expand Up @@ -366,6 +367,6 @@ public String escapeQuotationMark(String input) {
}

public void setMainPackage(String mainPackage) {
this.mainPackage = mainPackage;
this.configKeyPath = this.mainPackage = mainPackage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class {{classname}}(baseUrl: String) {
{{/javadocRenderer}}
def {{operationId}}({{>methodParameters}}): ApiRequest[{{>operationReturnType}}] =
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)
{{/isBasic}}{{/authMethods}}{{#bodyParam}}.withBody({{paramName}})
{{/bodyParam}}{{#formParams}}.withFormParam({{>paramCreation}})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object ApiInvoker {
*
* @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]] =
response(ec, system, invoker)
Expand All @@ -67,7 +67,7 @@ object ApiInvoker {
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) =>
ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(s)
}, {
Expand Down Expand Up @@ -215,7 +215,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
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
val request = createRequest(makeUri(r), r)
Expand All @@ -239,8 +239,8 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
.flatMap(unmarshallApiResponse(r))
}
def unmarshallApiResponse[T](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
def responseForState[V](state: ResponseState, value: V) = {
def unmarshallApiResponse[T: Manifest](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
def responseForState[V](state: ResponseState, value: V): ApiResponse[V] = {
state match {
case ResponseState.Success =>
ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
Expand All @@ -253,31 +253,29 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
)
}
}
val mf = implicitly(manifest[T])
request
.responseForCode(response.status.intValue)
.map {
case (Manifest.Unit, state: ResponseState) =>
// FIXME Casting is ugly, how to do better?
Future(responseForState(state, Unit)).asInstanceOf[Future[ApiResponse[T]]]
case (manifest: Manifest[T], state: ResponseState) =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](manifest, serialization, formats)
Unmarshal(response.entity)
.to[T]
.recoverWith {
case e ⇒ throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
}
.map(value => responseForState(state, value))
}
.getOrElse(Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString))))
.responseForCode(response.status.intValue) match {
case Some((Manifest.Unit, state: ResponseState)) =>
Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]])
case Some((manifest, state: ResponseState)) if manifest == mf =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
Unmarshal(response.entity)
.to[T]
.recoverWith {
case e ⇒ throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
}
.map(value => responseForState(state, value))
case None | Some(_) =>
Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString)))
}
}
}
sealed trait CustomContentTypes {
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 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{{>licenseInfo}}
package {{package}}

{{#imports}}
import {{import}}
{{/imports}}
import {{mainPackage}}.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID

{{#models}}
{{#model}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ object ApiKeyLocations {
case object HEADER extends ApiKeyLocation
case object COOKIE extends ApiKeyLocation
}


Expand Down
18 changes: 18 additions & 0 deletions modules/openapi-generator/src/test/resources/3_0/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ paths:
description: ''
operationId: addPet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
Expand All @@ -41,6 +50,15 @@ paths:
description: ''
operationId: updatePet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
*/
package hello.world.model

import hello.world.core.ApiModel
import org.joda.time.DateTime
import java.util.UUID
import hello.world.core.ApiModel

case class SomeObj (
`type`: Option[SomeObjEnums.`Type`] = None,
Expand Down
8 changes: 8 additions & 0 deletions samples/client/petstore/scala-akka/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ Class | Method | HTTP request | Description

- [ApiResponse](ApiResponse.md)
- [Category](Category.md)
- [InlineObject](InlineObject.md)
- [InlineObject1](InlineObject1.md)
- [Order](Order.md)
- [Pet](Pet.md)
- [Tag](Tag.md)
Expand All @@ -106,6 +108,12 @@ Authentication schemes defined for the API:
- **API key parameter name**: api_key
- **Location**: HTTP header

### auth_cookie

- **Type**: API key
- **API key parameter name**: AUTH_KEY
- **Location**:


## Author

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.2.8
sbt.version=1.3.6
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ class PetApi(baseUrl: String) {

/**
* Expected answers:
* code 200 : Pet (successful operation)
* 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] =
ApiRequest[Unit](ApiMethods.POST, baseUrl, "/pet", "application/json")
.withBody(body)
def addPet(pet: Pet): ApiRequest[Pet] =
ApiRequest[Pet](ApiMethods.POST, baseUrl, "/pet", "application/json")
.withBody(pet)
.withSuccessResponse[Pet](200)
.withErrorResponse[Unit](405)


Expand Down Expand Up @@ -107,15 +109,17 @@ class PetApi(baseUrl: String) {

/**
* Expected answers:
* code 200 : Pet (successful operation)
* code 400 : (Invalid ID supplied)
* code 404 : (Pet not found)
* 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] =
ApiRequest[Unit](ApiMethods.PUT, baseUrl, "/pet", "application/json")
.withBody(body)
def updatePet(pet: Pet): ApiRequest[Pet] =
ApiRequest[Pet](ApiMethods.PUT, baseUrl, "/pet", "application/json")
.withBody(pet)
.withSuccessResponse[Pet](200)
.withErrorResponse[Unit](400)
.withErrorResponse[Unit](404)
.withErrorResponse[Unit](405)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ class StoreApi(baseUrl: String) {
* code 200 : Order (successful operation)
* 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")
.withBody(body)
.withBody(order)
.withSuccessResponse[Order](200)
.withErrorResponse[Unit](400)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,47 @@ class UserApi(baseUrl: String) {
* Expected answers:
* 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")
.withBody(body)
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit]


/**
* Expected answers:
* 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")
.withBody(body)
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit]


/**
* Expected answers:
* 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")
.withBody(body)
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withDefaultSuccessResponse[Unit]


Expand All @@ -68,10 +80,14 @@ class UserApi(baseUrl: String) {
* code 400 : (Invalid username supplied)
* code 404 : (User not found)
*
* Available security schemes:
* auth_cookie (apiKey)
*
* @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")
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withPathParam("username", username)
.withErrorResponse[Unit](400)
.withErrorResponse[Unit](404)
Expand All @@ -97,6 +113,7 @@ class UserApi(baseUrl: String) {
* Expected answers:
* code 200 : String (successful operation)
* 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-Expires-After - date in UTC when toekn expires
* code 400 : (Invalid username/password supplied)
Expand All @@ -112,16 +129,21 @@ class UserApi(baseUrl: String) {
.withErrorResponse[Unit](400)

object LoginUserHeaders {
def setCookie(r: ApiReturnWithHeaders) = r.getStringHeader("Set-Cookie")
def xRateLimit(r: ApiReturnWithHeaders) = r.getIntHeader("X-Rate-Limit")
def xExpiresAfter(r: ApiReturnWithHeaders) = r.getDateTimeHeader("X-Expires-After")
}

/**
* Expected answers:
* 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")
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withDefaultSuccessResponse[Unit]


Expand All @@ -132,12 +154,16 @@ class UserApi(baseUrl: String) {
* code 400 : (Invalid user supplied)
* code 404 : (User not found)
*
* Available security schemes:
* auth_cookie (apiKey)
*
* @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")
.withBody(body)
.withApiKey(apiKey, "AUTH_KEY", COOKIE)
.withBody(user)
.withPathParam("username", username)
.withErrorResponse[Unit](400)
.withErrorResponse[Unit](404)
Expand Down
Loading

0 comments on commit 1bba3a5

Please sign in to comment.