Skip to content

Commit de9ff5a

Browse files
committed
[scala][http4s] fix escaping of reserved words for correct model deserialization
1 parent 6fdb632 commit de9ff5a

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaHttp4sServerCodegen.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.openapitools.codegen.languages;
1818

19+
import com.samskivert.mustache.Escapers;
20+
import com.samskivert.mustache.Mustache;
1921
import io.swagger.v3.oas.models.media.Schema;
2022
import org.openapitools.codegen.*;
2123
import org.openapitools.codegen.meta.features.*;
@@ -557,7 +559,34 @@ public String getHelp() {
557559

558560
@Override
559561
public String escapeReservedWord(String name) {
560-
return "_" + name;
562+
if (this.reservedWordsMappings().containsKey(name)) {
563+
return this.reservedWordsMappings().get(name);
564+
}
565+
// Reserved words will be further escaped at the mustache compiler level.
566+
// Scala escaping done here (via `, without compiler escaping) would otherwise be HTML encoded.
567+
return "`" + name + "`";
568+
}
569+
570+
@Override
571+
public Mustache.Compiler processCompiler(Mustache.Compiler compiler) {
572+
Mustache.Escaper SCALA = new Mustache.Escaper() {
573+
@Override
574+
public String escape(String text) {
575+
// Fix included as suggested by akkie in #6393
576+
// The given text is a reserved word which is escaped by enclosing it with grave accents. If we would
577+
// escape that with the default Mustache `HTML` escaper, then the escaper would also escape our grave
578+
// accents. So we remove the grave accents before the escaping and add it back after the escaping.
579+
if (text.startsWith("`") && text.endsWith("`")) {
580+
String unescaped = text.substring(1, text.length() - 1);
581+
return "`" + Escapers.HTML.escape(unescaped) + "`";
582+
}
583+
584+
// All none reserved words will be escaped with the default Mustache `HTML` escaper
585+
return Escapers.HTML.escape(text);
586+
}
587+
};
588+
589+
return compiler.withEscaper(SCALA);
561590
}
562591

563592
@Override

samples/server/petstore/scala-http4s-server/src/main/scala/org/openapitools/apis/FakeApi.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ final case class FakeApiRoutes[
2424
object varQueryParam extends OptionalQueryParamDecoderMatcher[String]("var")
2525

2626
val route = HttpRoutes.of[F] {
27-
case req @ GET -> Root / "fake" / "user" / _type :? varQueryParam(_var) =>
28-
delegate.reservedWords.handle(req, _type, _var, responses)
27+
case req @ GET -> Root / "fake" / "user" / `type` :? varQueryParam(`var`) =>
28+
delegate.reservedWords.handle(req, `type`, `var`, responses)
2929

3030
}
3131

@@ -57,8 +57,8 @@ trait FakeApiDelegate[F[_]] {
5757

5858
def handle(
5959
req: Request[F],
60-
_type: String,
61-
_var: Option[String],
60+
`type`: String,
61+
`var`: Option[String],
6262
responses: reservedWordsResponses[F]
6363
): F[Response[F]]
6464

samples/server/petstore/scala-http4s-server/src/main/scala/org/openapitools/models/types.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import java.time.ZonedDateTime
1515
/**
1616
* Describes the result of uploading an image resource
1717
* @param code
18-
* @param _type
18+
* @param `type`
1919
* @param message
2020
*/
2121

2222
case class ApiResponse(
2323
code: Option[Int],
24-
_type: Option[String],
24+
`type`: Option[String],
2525
message: Option[String]
2626
)
2727
object ApiResponse {

0 commit comments

Comments
 (0)