Skip to content

Commit 6229c79

Browse files
Bump async-http-client
1 parent 9bba233 commit 6229c79

File tree

10 files changed

+62
-73
lines changed

10 files changed

+62
-73
lines changed

cloudinary-core/build.sbt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pomExtra := {
3535
}
3636

3737
libraryDependencies ++= Seq(
38-
"com.ning" % "async-http-client" % "1.9.40",
38+
"org.asynchttpclient" % "async-http-client" % "3.0.3",
3939
"org.json4s" %% "json4s-native" % "3.6.10",
4040
"org.json4s" %% "json4s-ext" % "3.6.10",
4141
"org.scalatest" %% "scalatest" % "3.2.2" % "test",
@@ -48,4 +48,3 @@ libraryDependencies += "org.scalamock" %% "scalamock-scalatest-support" % "3.4.1
4848
resolvers ++= Seq("sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", "sonatype releases" at "https://oss.sonatype.org/content/repositories/releases")
4949

5050
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
51-

cloudinary-core/src/main/scala/com/cloudinary/Api.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package com.cloudinary
33
import java.util.Date
44
import java.util.TimeZone
55
import scala.concurrent.Future
6-
import com.ning.http.client.Realm
7-
import com.ning.http.client.RequestBuilder
6+
import org.asynchttpclient.Realm
7+
import org.asynchttpclient.RequestBuilder
88
import response._
99
import parameters.UpdateParameters
1010
import java.text.SimpleDateFormat
@@ -55,9 +55,7 @@ class Api(implicit cloudinary: Cloudinary) {
5555
}
5656
}
5757

58-
val realm = new Realm.RealmBuilder()
59-
.setPrincipal(cloudinary.apiKey())
60-
.setPassword(cloudinary.apiSecret())
58+
val realm = new Realm.Builder(cloudinary.apiKey(), cloudinary.apiSecret())
6159
.setUsePreemptiveAuth(true)
6260
.setScheme(Realm.AuthScheme.BASIC)
6361
.build()

cloudinary-core/src/main/scala/com/cloudinary/AsyncCloudinaryHandler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.cloudinary
22

33
import scala.concurrent.Promise
44

5-
import _root_.com.ning.http.client.{
5+
import _root_.org.asynchttpclient.{
66
AsyncHandler,
77
AsyncCompletionHandler,
88
HttpResponseStatus,
@@ -68,4 +68,4 @@ class AsyncCloudinaryHandler[JValue](result: Promise[JsonAST.JValue]) extends As
6868
case Left(e) => result.failure(e)
6969
}
7070
}
71-
}
71+
}

cloudinary-core/src/main/scala/com/cloudinary/Cloudinary.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import java.security.NoSuchAlgorithmException
66
import java.net.URI
77
import java.net.URLDecoder
88
import java.io.UnsupportedEncodingException
9-
import _root_.com.ning.http.client.RequestBuilder
9+
import _root_.org.asynchttpclient.RequestBuilder
1010

1111
object Cloudinary {
1212
final val CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net";
@@ -60,7 +60,7 @@ object Cloudinary {
6060
val digest = sign(params.mkString("&"), apiSecret)
6161
bytes2Hex(digest).toLowerCase()
6262
}
63-
63+
6464
def sign(toSign:String, apiSecret: String) = {
6565
var md: MessageDigest = null
6666
try {

cloudinary-core/src/main/scala/com/cloudinary/HttpClient.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package com.cloudinary
22

33
import java.util.concurrent.atomic.AtomicReference
4+
import java.time.Duration
45

5-
import com.ning.http.client.AsyncHttpClientConfig
6-
import com.ning.http.client.AsyncHttpClient
6+
import org.asynchttpclient.{AsyncHttpClient, DefaultAsyncHttpClient, DefaultAsyncHttpClientConfig}
77
import org.json4s._
88
import org.json4s.native.JsonMethods._
99

1010
import scala.concurrent.{Future, Promise}
11-
import com.ning.http.client.Request
11+
import org.asynchttpclient.Request
1212

1313
import concurrent.ExecutionContext.Implicits.global
1414
import com.cloudinary.response.RawResponse
@@ -53,10 +53,11 @@ object HttpClient {
5353

5454
private[cloudinary] def newClient(): AsyncHttpClient = {
5555

56-
val asyncHttpConfig = new AsyncHttpClientConfig.Builder()
57-
asyncHttpConfig.setUserAgent(Cloudinary.USER_AGENT)
58-
asyncHttpConfig.setReadTimeout(-1)
59-
new AsyncHttpClient(asyncHttpConfig.build())
56+
val asyncHttpConfig = new DefaultAsyncHttpClientConfig.Builder()
57+
.setUserAgent(Cloudinary.USER_AGENT)
58+
.setReadTimeout(Duration.ofMillis(-1))
59+
.build()
60+
new DefaultAsyncHttpClient(asyncHttpConfig)
6061
}
6162

6263
/**

cloudinary-core/src/main/scala/com/cloudinary/Uploader.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package com.cloudinary
22

33
import java.io._
44
import java.nio.charset.StandardCharsets
5+
import java.time.Duration
56

67
import com.cloudinary.parameters._
78
import com.cloudinary.response._
8-
import com.ning.http.client.RequestBuilder
9-
import com.ning.http.client.multipart.{ByteArrayPart, FilePart, StringPart}
9+
import org.asynchttpclient.RequestBuilder
10+
import org.asynchttpclient.request.body.multipart.{ByteArrayPart, FilePart, StringPart}
1011
import org.json4s.JsonDSL._
1112
import org.json4s.native.JsonMethods._
1213

@@ -31,7 +32,7 @@ class Uploader(implicit val cloudinary: Cloudinary) {
3132

3233
val apiUrlBuilder = new RequestBuilder("POST")
3334
apiUrlBuilder.setUrl(apiUrl)
34-
requestTimeout.map(timeout => apiUrlBuilder.setRequestTimeout(timeout)) //in milliseconds
35+
requestTimeout.map(timeout => apiUrlBuilder.setRequestTimeout(Duration.ofMillis(timeout))) //in milliseconds
3536

3637
processedParams foreach {
3738
param =>
@@ -40,10 +41,10 @@ class Uploader(implicit val cloudinary: Cloudinary) {
4041
case list: Iterable[_] => list.foreach {
4142
v =>
4243
apiUrlBuilder.addBodyPart(
43-
new StringPart(k + "[]", v.toString, StringPart.DEFAULT_CONTENT_TYPE, StandardCharsets.UTF_8))
44+
new StringPart(k + "[]", v.toString))
4445
}
4546
case null =>
46-
case _ => apiUrlBuilder.addBodyPart(new StringPart(k, v.toString, StringPart.DEFAULT_CONTENT_TYPE, StandardCharsets.UTF_8))
47+
case _ => apiUrlBuilder.addBodyPart(new StringPart(k, v.toString))
4748
}
4849
}
4950

@@ -52,7 +53,7 @@ class Uploader(implicit val cloudinary: Cloudinary) {
5253
case fp: FilePart => apiUrlBuilder.addBodyPart(fp)
5354
case f: File => apiUrlBuilder.addBodyPart(new FilePart("file", f))
5455
case fn: String if !fn.matches(illegalFileName) => apiUrlBuilder.addBodyPart(new FilePart("file", new File(fn)))
55-
case body: String => apiUrlBuilder.addBodyPart(new StringPart("file", body, StringPart.DEFAULT_CONTENT_TYPE, StandardCharsets.UTF_8))
56+
case body: String => apiUrlBuilder.addBodyPart(new StringPart("file", body))
5657
case body: Array[Byte] => apiUrlBuilder.addBodyPart(new ByteArrayPart("file", body))
5758
case null =>
5859
case _ => throw new IOException("Unrecognized file parameter " + file);

cloudinary-core/src/main/scala/com/cloudinary/Url.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.cloudinary
22

33
import java.net.URLDecoder
4-
import com.ning.http.util.Base64
4+
import java.util.Base64
55

66
case class Url(
77
cloudName: String,
@@ -154,7 +154,7 @@ case class Url(
154154
val signature = if (signUrl) {
155155
val toSign = List(transformationStr, Some(signableSource)).flatten.mkString("/")
156156
Some("s--" +
157-
Base64.encode(Cloudinary.sign(toSign, apiSecret.getOrElse(throw new Exception("Must supply api secret to sign URLs")))).
157+
Base64.getEncoder.encodeToString(Cloudinary.sign(toSign, apiSecret.getOrElse(throw new Exception("Must supply api secret to sign URLs")))).
158158
take(8).
159159
replace('+', '-').replace('/', '_') + "--")
160160
} else None

cloudinary-core/src/test/scala/com/cloudinary/ApiSpec.scala

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import java.util.{Date, TimeZone}
88
import com.cloudinary.Implicits._
99
import com.cloudinary.parameters._
1010
import com.cloudinary.response._
11-
import com.ning.http.client._
11+
import org.asynchttpclient._
1212
import org.scalamock.scalatest.MockFactory
1313
import org.scalatest._
1414
import matchers.should._
@@ -85,11 +85,10 @@ class ApiSpec extends MockableFlatSpec with Matchers with OptionValues with Insi
8585
it should "allow listing resources with cursor" in {
8686
val cursor = "OJNASGONQG0230JGV0JV3Q0IDVO"
8787
val (provider, api) = mockApi()
88-
(provider.execute _) expects where { (request: Request, _) => {
88+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
8989
val params = getQuery(request)
9090
params.contains(("next_cursor", cursor))
9191
}
92-
}
9392
api.resources(maxResults = 1, nextCursor = cursor)
9493
}
9594

@@ -139,12 +138,11 @@ class ApiSpec extends MockableFlatSpec with Matchers with OptionValues with Insi
139138
df.setTimeZone(TimeZone.getTimeZone("UTC"))
140139
val (provider, api) = mockApi()
141140
val startAt = df.parse("22 Aug 2016 07:57:34 UTC")
142-
(provider.execute _) expects where { (request: Request, *) => {
141+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
143142
val params = getQuery(request)
144143
params.contains(("start_at", "22 Aug 2016 07:57:34 UTC GMT")) &&
145144
params.contains(("direction", "asc"))
146145
}
147-
}
148146
api.resources(`type` = "upload", startAt = Some(startAt), direction = Some(Api.ASCENDING))
149147
}
150148

@@ -244,9 +242,8 @@ class ApiSpec extends MockableFlatSpec with Matchers with OptionValues with Insi
244242

245243
it should "allow listing transformations with next_cursor" in {
246244
val (provider, api) = mockApi()
247-
(provider.execute _) expects where { (request: Request, *) => {
248-
request.getQueryParams.contains(new Param("next_cursor", "1234567"))
249-
}
245+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
246+
request.getQueryParams.contains(new Param("next_cursor", "1234567"))
250247
}
251248
api.transformations(nextCursor = "1234567")
252249
}
@@ -282,24 +279,21 @@ class ApiSpec extends MockableFlatSpec with Matchers with OptionValues with Insi
282279
val t = Transformation().c_("scale").w_(100)
283280
val (provider, api) = mockApi()
284281
inSequence {
285-
(provider.execute _) expects where {
286-
(request: Request, *) => {
282+
(provider.executeRequest _) expects where {
283+
(request: Request, _: AsyncHandler[_]) =>
287284
request.getQueryParams.contains(new Param("next_cursor", "1234567")) &&
288285
request.getUrl.matches(".+/" + apiTestTransformation + "?.+")
289-
}
290286
}
291-
(provider.execute _) expects where {
292-
(request: Request, *) => {
287+
(provider.executeRequest _) expects where {
288+
(request: Request, _: AsyncHandler[_]) =>
293289
request.getQueryParams.contains(new Param("next_cursor", "1234567")) &&
294290
request.getUrl.matches(".+/" + apiTestTransformation + "?.+")
295-
}
296291
}
297-
(provider.execute _) expects where {
298-
(request: Request, *) => {
292+
(provider.executeRequest _) expects where {
293+
(request: Request, _: AsyncHandler[_]) =>
299294
request.getQueryParams.contains(new Param("max_results", "111")) &&
300295
!request.getQueryParams.asScala.exists(p => p.getName == "next_cursor") &&
301296
request.getUrl.matches(".+/" + apiTestTransformation + "?.+")
302-
}
303297
}
304298
}
305299
api.transformationByName(apiTestTransformation, "1234567")
@@ -309,10 +303,9 @@ class ApiSpec extends MockableFlatSpec with Matchers with OptionValues with Insi
309303

310304
it should "allow listing transformation by name with next_cursor" in {
311305
val (provider, api) = mockApi()
312-
provider.execute _ expects where {
313-
(request: Request, handler: AsyncHandler[Nothing]) => {
306+
(provider.executeRequest _) expects where {
307+
(request: Request, _: AsyncHandler[_]) =>
314308
request.getQueryParams.contains(new Param("next_cursor", "1234567"))
315-
}
316309
}
317310
api.transformationByName(apiTestTransformation, nextCursor = "1234567")
318311
}

cloudinary-core/src/test/scala/com/cloudinary/MockableFlatSpec.scala

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ package com.cloudinary
22

33
import java.net.URLDecoder
44

5-
import com.ning.http.client.multipart.StringPart
6-
import com.ning.http.client.{AsyncHttpClient, AsyncHttpClientConfig, AsyncHttpProvider, Request}
5+
import org.asynchttpclient.request.body.multipart.StringPart
6+
import org.asynchttpclient.{AsyncHttpClient, DefaultAsyncHttpClientConfig, Request, AsyncHandler, ListenableFuture}
77
import org.scalamock.clazz.Mock
88
import org.scalamock.scalatest.MockFactory
99
import org.scalatest.flatspec.AnyFlatSpec
1010
import org.scalatest.BeforeAndAfterEach
1111

1212
import scala.collection.JavaConverters._
1313

14+
trait MockableAsyncHttpClient extends AsyncHttpClient {
15+
override def executeRequest[T](request: Request, handler: AsyncHandler[T]): ListenableFuture[T]
16+
}
17+
1418
class MockableFlatSpec extends AnyFlatSpec with MockFactory with BeforeAndAfterEach{
1519
protected val prefix = "cloudinary_scala"
1620
protected val suffix = sys.env.getOrElse("TRAVIS_JOB_ID", (10000 + scala.util.Random.nextInt(89999)).toString)
@@ -26,36 +30,34 @@ class MockableFlatSpec extends AnyFlatSpec with MockFactory with BeforeAndAfterE
2630
}
2731

2832
/**
29-
* Mock the AsyncHttpProvider so that calls do not invoke the server side.
30-
* Expectations can be set on the execute method of AsyncHttpProvider.
33+
* Mock the AsyncHttpClient so that calls do not invoke the server side.
34+
* Expectations can be set on the executeRequest method of AsyncHttpClient.
3135
* @return the mocked instance
3236
*/
3337
def mockHttp() = {
34-
val mockProvider: AsyncHttpProvider = mock[AsyncHttpProvider]
35-
val asyncHttpConfig = new AsyncHttpClientConfig.Builder()
36-
asyncHttpConfig.setUserAgent(Cloudinary.USER_AGENT)
37-
(mockProvider, new AsyncHttpClient(mockProvider, asyncHttpConfig.build()))
38+
val mockClient: MockableAsyncHttpClient = mock[MockableAsyncHttpClient]
39+
(mockClient, mockClient)
3840
}
3941

4042
/**
41-
* Returns an instance of [[com.cloudinary.Api Api]] with a mocked [[com.ning.http.client.AsyncHttpProvider AsyncHttpProvider]]
43+
* Returns an instance of [[com.cloudinary.Api Api]] with a mocked [[org.asynchttpclient.AsyncHttpClient AsyncHttpClient]]
4244
*/
4345
def mockApi() = {
4446
val api = cloudinary.api()
45-
val (mockProvider, client) = mockHttp()
47+
val (mockClient, client) = mockHttp()
4648
api.httpclient.client = client
47-
(mockProvider, api)
49+
(mockClient, api)
4850
}
4951

5052

5153
/**
52-
* Returns an instance of [[com.cloudinary.Uploader Uploader]] with a mocked [[com.ning.http.client.AsyncHttpProvider AsyncHttpProvider]]
54+
* Returns an instance of [[com.cloudinary.Uploader Uploader]] with a mocked [[org.asynchttpclient.AsyncHttpClient AsyncHttpClient]]
5355
*/
5456
def mockUploader() = {
5557
val uploader = cloudinary.uploader()
56-
val (mockProvider, client) = mockHttp()
58+
val (mockClient, client) = mockHttp()
5759
uploader.httpclient.client = client
58-
(mockProvider, uploader)
60+
(mockClient, uploader)
5961
}
6062

6163

@@ -65,7 +67,7 @@ class MockableFlatSpec extends AnyFlatSpec with MockFactory with BeforeAndAfterE
6567
* @return an array of tuples in the form of (name, value)
6668
*/
6769
def getParts(request: Request): scala.collection.mutable.Buffer[(String, String)] = {
68-
request.getParts.asScala.map(p => {
70+
request.getBodyParts.asScala.map(p => {
6971
val sp = p.asInstanceOf[StringPart]
7072
(sp.getName, sp.getValue)
7173
})

cloudinary-core/src/test/scala/com/cloudinary/UploaderSpec.scala

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import java.util.concurrent.TimeoutException
55
import com.cloudinary.Implicits._
66
import com.cloudinary.parameters._
77
import com.cloudinary.response._
8-
import com.ning.http.client.Request
9-
import com.ning.http.client.multipart.StringPart
8+
import org.asynchttpclient.{Request, AsyncHandler, ListenableFuture}
9+
import org.asynchttpclient.request.body.multipart.StringPart
1010
import org.scalatest.{BeforeAndAfterAll, Inside, OptionValues, Tag, matchers}
1111
import matchers.should._
1212

@@ -204,25 +204,20 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
204204

205205
it should "support generating sprites" in {
206206
val sprite_test_tag: String = "sprite_test_tag" + suffix
207-
val (provider, uploader )= mockUploader()
208-
val tagPart: StringPart = new StringPart("tag", sprite_test_tag, "UTF-8")
209-
(provider.execute _) expects where { (request: Request, *) => {
210-
val map = getParts(request)
211-
map.contains(("tag", sprite_test_tag))
212-
}
207+
val (provider, uploader) = mockUploader()
208+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
209+
getParts(request).contains(("tag", sprite_test_tag))
213210
}
214-
(provider.execute _) expects where { (request: Request, *) => {
211+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
215212
val map = getParts(request)
216213
map.contains(("tag", sprite_test_tag)) &&
217214
map.contains(("transformation", "w_100"))
218215
}
219-
}
220-
(provider.execute _) expects where { (request: Request, *) => {
216+
(provider.executeRequest _) expects where { (request: Request, _: AsyncHandler[_]) =>
221217
val map = getParts(request)
222218
map.contains(("tag", sprite_test_tag)) &&
223219
map.contains(("transformation", "f_jpg,w_100"))
224220
}
225-
}
226221
uploader.generateSprite(sprite_test_tag)
227222
uploader.generateSprite(sprite_test_tag, transformation = new Transformation().w_(100))
228223
uploader.generateSprite(sprite_test_tag, transformation = new Transformation().w_(100), format = "jpg")

0 commit comments

Comments
 (0)