Skip to content

Commit 0a9e378

Browse files
gmarzwing328
authored andcommitted
[Scala] Add support for PATCH via X-HTTP-Method-Override (#6539)
* Added support for http PATCH to the scala client using X-HTTP-Method-Override header * Update Petstore sample
1 parent d325c6e commit 0a9e378

File tree

9 files changed

+146
-60
lines changed

9 files changed

+146
-60
lines changed

modules/swagger-codegen/src/main/resources/scala/apiInvoker.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper,
142142
case "DELETE" => {
143143
builder.delete(classOf[ClientResponse])
144144
}
145+
case "PATCH" => {
146+
if(formData != null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], formData)
147+
else if(body == null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], null)
148+
else builder.header("X-HTTP-Method-Override", "PATCH").`type`(contentType).post(classOf[ClientResponse], serialize(body))
149+
}
145150
case _ => null
146151
}
147152
response.getStatusInfo().getStatusCode() match {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2.3.0-SNAPSHOT

samples/client/petstore-security-test/scala/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ ext {
104104
jackson_version = "2.4.2"
105105
junit_version = "4.8.1"
106106
scala_test_version = "2.2.4"
107+
swagger_async_httpclient_version = "0.3.5"
108+
}
109+
110+
repositories {
111+
mavenLocal()
112+
mavenCentral()
107113
}
108114

109115
dependencies {
@@ -117,4 +123,5 @@ dependencies {
117123
testCompile "junit:junit:$junit_version"
118124
compile "joda-time:joda-time:$jodatime_version"
119125
compile "org.joda:joda-convert:$joda_version"
126+
compile "com.wordnik.swagger:swagger-async-httpclient_2.10:$swagger_async_httpclient_version"
120127
}
Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
1-
lazy val root = (project in file(".")).
2-
settings(
3-
version := "1.0.0",
4-
name := "swagger-scala-client",
5-
organization := "io.swagger",
6-
scalaVersion := "2.11.8",
7-
8-
libraryDependencies ++= Seq(
9-
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.4.2",
10-
"com.sun.jersey" % "jersey-core" % "1.19",
11-
"com.sun.jersey" % "jersey-client" % "1.19",
12-
"com.sun.jersey.contribs" % "jersey-multipart" % "1.19",
13-
"org.jfarcand" % "jersey-ahc-client" % "1.0.5",
14-
"io.swagger" % "swagger-core" % "1.5.8",
15-
"joda-time" % "joda-time" % "2.2",
16-
"org.joda" % "joda-convert" % "1.2",
17-
"org.scalatest" %% "scalatest" % "2.2.4" % "test",
18-
"junit" % "junit" % "4.8.1" % "test"
19-
),
20-
21-
resolvers ++= Seq(
22-
Resolver.jcenterRepo,
23-
Resolver.mavenLocal
24-
),
25-
26-
scalacOptions := Seq(
27-
"-unchecked",
28-
"-deprecation",
29-
"-feature"
30-
),
31-
32-
publishArtifact in (Compile, packageDoc) := false
33-
)
1+
version := "1.0.0"
2+
3+
name := "swagger-scala-client"
4+
5+
organization := "io.swagger"
6+
7+
scalaVersion := "2.11.8"
8+
9+
libraryDependencies ++= Seq(
10+
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.4.2",
11+
"com.sun.jersey" % "jersey-core" % "1.19",
12+
"com.sun.jersey" % "jersey-client" % "1.19",
13+
"com.sun.jersey.contribs" % "jersey-multipart" % "1.19",
14+
"org.jfarcand" % "jersey-ahc-client" % "1.0.5",
15+
"io.swagger" % "swagger-core" % "1.5.8",
16+
"joda-time" % "joda-time" % "2.2",
17+
"org.joda" % "joda-convert" % "1.2",
18+
"org.scalatest" %% "scalatest" % "2.2.4" % "test",
19+
"junit" % "junit" % "4.8.1" % "test",
20+
"com.wordnik.swagger" %% "swagger-async-httpclient" % "0.3.5"
21+
)
22+
23+
resolvers ++= Seq(
24+
Resolver.mavenLocal
25+
)
26+
27+
scalacOptions := Seq(
28+
"-unchecked",
29+
"-deprecation",
30+
"-feature"
31+
)
32+
33+
publishArtifact in (Compile, packageDoc) := false
34+

samples/client/petstore-security-test/scala/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@
209209
<artifactId>joda-convert</artifactId>
210210
<version>${joda-version}</version>
211211
</dependency>
212+
<dependency>
213+
<groupId>com.wordnik.swagger</groupId>
214+
<artifactId>swagger-async-httpclient_2.10</artifactId>
215+
<version>${swagger-async-httpclient-version}</version>
216+
</dependency>
212217
</dependencies>
213218
<properties>
214219
<scala-version>2.10.4</scala-version>
@@ -223,6 +228,7 @@
223228
<junit-version>4.8.1</junit-version>
224229
<scala-maven-plugin-version>3.1.5</scala-maven-plugin-version>
225230
<scala-test-version>2.2.4</scala-test-version>
231+
<swagger-async-httpclient-version>0.3.5</swagger-async-httpclient-version>
226232

227233
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
228234
</properties>

samples/client/petstore-security-test/scala/src/main/scala/io/swagger/client/ApiInvoker.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper,
153153
case "DELETE" => {
154154
builder.delete(classOf[ClientResponse])
155155
}
156+
case "PATCH" => {
157+
if(formData != null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], formData)
158+
else if(body == null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], null)
159+
else builder.header("X-HTTP-Method-Override", "PATCH").`type`(contentType).post(classOf[ClientResponse], serialize(body))
160+
}
156161
case _ => null
157162
}
158163
response.getStatusInfo().getStatusCode() match {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.swagger.client
2+
3+
import io.swagger.client.api._
4+
5+
import com.wordnik.swagger.client._
6+
7+
import java.io.Closeable
8+
9+
class AsyncClient(config: SwaggerConfig) extends Closeable {
10+
val locator = config.locator
11+
val name = config.name
12+
13+
private[this] val client = transportClient
14+
15+
protected def transportClient: TransportClient = new RestClient(config)
16+
17+
def close() {
18+
client.close()
19+
}
20+
}

samples/client/petstore-security-test/scala/src/main/scala/io/swagger/client/api/FakeApi.scala

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212

1313
package io.swagger.client.api
1414

15-
import io.swagger.client.ApiInvoker
16-
import io.swagger.client.ApiException
15+
import java.text.SimpleDateFormat
16+
17+
import io.swagger.client.{ApiInvoker, ApiException}
1718

1819
import com.sun.jersey.multipart.FormDataMultiPart
1920
import com.sun.jersey.multipart.file.FileDataBodyPart
@@ -25,12 +26,41 @@ import java.util.Date
2526

2627
import scala.collection.mutable.HashMap
2728

29+
import com.wordnik.swagger.client._
30+
import scala.concurrent.Future
31+
import collection.mutable
32+
33+
import java.net.URI
34+
35+
import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._
36+
import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._
37+
38+
import scala.concurrent.ExecutionContext.Implicits.global
39+
import scala.concurrent._
40+
import scala.concurrent.duration._
41+
import scala.util.{Failure, Success, Try}
42+
2843
class FakeApi(val defBasePath: String = "https://petstore.swagger.io *_/ ' \" =end -- \\r\\n \\n \\r/v2 *_/ ' \" =end -- \\r\\n \\n \\r",
2944
defApiInvoker: ApiInvoker = ApiInvoker) {
45+
46+
implicit val formats = new org.json4s.DefaultFormats {
47+
override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+0000")
48+
}
49+
implicit val stringReader = ClientResponseReaders.StringReader
50+
implicit val unitReader = ClientResponseReaders.UnitReader
51+
implicit val jvalueReader = ClientResponseReaders.JValueReader
52+
implicit val jsonReader = JsonFormatsReader
53+
implicit val stringWriter = RequestWriters.StringWriter
54+
implicit val jsonWriter = JsonFormatsWriter
55+
3056
var basePath = defBasePath
3157
var apiInvoker = defApiInvoker
3258

33-
def addHeader(key: String, value: String) = apiInvoker.defaultHeaders += key -> value
59+
def addHeader(key: String, value: String) = apiInvoker.defaultHeaders += key -> value
60+
61+
val config = SwaggerConfig.forUrl(new URI(defBasePath))
62+
val client = new RestClient(config)
63+
val helper = new FakeApiAsyncHelper(client, config)
3464

3565
/**
3666
* To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
@@ -39,37 +69,43 @@ class FakeApi(val defBasePath: String = "https://petstore.swagger.io *_/ ' \" =e
3969
* @return void
4070
*/
4171
def testCodeInject * &#39; &quot; &#x3D;end rn n r(testCodeInjectEndRnNR: Option[String] = None) = {
42-
// create path and map variables
43-
val path = "/fake".replaceAll("\\{format\\}", "json")
72+
val await = Try(Await.result(testCodeInject * &#39; &quot; &#x3D;end rn n rAsync(testCodeInjectEndRnNR), Duration.Inf))
73+
await match {
74+
case Success(i) => Some(await.get)
75+
case Failure(t) => None
76+
}
77+
}
4478

45-
val contentTypes = List("application/json", "*_/ ' =end -- ")
46-
val contentType = contentTypes(0)
79+
/**
80+
* To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r asynchronously
81+
*
82+
* @param testCodeInjectEndRnNR To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r (optional)
83+
* @return Future(void)
84+
*/
85+
def testCodeInject * &#39; &quot; &#x3D;end rn n rAsync(testCodeInjectEndRnNR: Option[String] = None) = {
86+
helper.testCodeInject * &#39; &quot; &#x3D;end rn n r(testCodeInjectEndRnNR)
87+
}
4788

48-
val queryParams = new HashMap[String, String]
49-
val headerParams = new HashMap[String, String]
50-
val formParams = new HashMap[String, String]
5189

52-
90+
}
5391

54-
var postBody: AnyRef = null
92+
class FakeApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) {
5593

56-
if (contentType.startsWith("multipart/form-data")) {
57-
val mp = new FormDataMultiPart
58-
testCodeInjectEndRnNR.map(paramVal => mp.field("test code inject */ &#39; &quot; &#x3D;end -- \r\n \n \r", paramVal.toString, MediaType.MULTIPART_FORM_DATA_TYPE))
59-
postBody = mp
60-
} else {
61-
testCodeInjectEndRnNR.map(paramVal => formParams += "test code inject */ &#39; &quot; &#x3D;end -- \r\n \n \r" -> paramVal.toString)
62-
}
94+
def testCodeInject * &#39; &quot; &#x3D;end rn n r(testCodeInjectEndRnNR: Option[String] = None
95+
)(implicit reader: ClientResponseReader[Unit]): Future[Unit] = {
96+
// create path and map variables
97+
val path = (addFmt("/fake"))
98+
99+
// query params
100+
val queryParams = new mutable.HashMap[String, String]
101+
val headerParams = new mutable.HashMap[String, String]
63102

64-
try {
65-
apiInvoker.invokeApi(basePath, path, "PUT", queryParams.toMap, formParams.toMap, postBody, headerParams.toMap, contentType) match {
66-
case s: String =>
67-
case _ => None
68-
}
69-
} catch {
70-
case ex: ApiException if ex.code == 404 => None
71-
case ex: ApiException => throw ex
103+
104+
val resFuture = client.submit("PUT", path, queryParams.toMap, headerParams.toMap, "")
105+
resFuture flatMap { resp =>
106+
process(reader.read(resp))
72107
}
73108
}
74109

110+
75111
}

samples/client/petstore/scala/src/main/scala/io/swagger/client/ApiInvoker.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper,
153153
case "DELETE" => {
154154
builder.delete(classOf[ClientResponse])
155155
}
156+
case "PATCH" => {
157+
if(formData != null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], formData)
158+
else if(body == null) builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], null)
159+
else builder.header("X-HTTP-Method-Override", "PATCH").`type`(contentType).post(classOf[ClientResponse], serialize(body))
160+
}
156161
case _ => null
157162
}
158163
response.getStatusInfo().getStatusCode() match {

0 commit comments

Comments
 (0)