SocketTimeoutException when I use Scalaj request
Asked Answered
T

2

10

I'm trying to make a simple https request using this library https://github.com/scalaj/scalaj-http . The request contains some json data.

Here is what I'm doing:

  val jsonHeaders = """{"jsonrpc": "2.0", "method": "someMethod", "params": {"dataIds":["12348" , "456"]}, "data2": "777"}"""

  val result = Http.postData("https://someurl.com/json-rpc", jsonHeaders)
    .header("content-type", "application/json")
    .header("X-Application", "myCode")
    .header("X-Authentication", "myCode2")
    .option(HttpOptions.readTimeout(10000))
    .asString
    //.responseCode -- the same error

  println(result)

And it always returns me a timeout error:

[error] (run-main) java.net.SocketTimeoutException: connect timed out
java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.connect(Unknown Source)
    at sun.net.NetworkClient.doConnect(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.<init>(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.New(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)
    at scalaj.http.Http$$anonfun$3.apply(Http.scala:263)
    at scalaj.http.Http$$anonfun$3.apply(Http.scala:261)
    at scalaj.http.Http$Request.process(Http.scala:102)
    at scalaj.http.Http$Request.apply(Http.scala:90)
    at scalaj.http.Http$Request.asString(Http.scala:133)
    at Application$delayedInit$body.apply(Application.scala:27)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
    at scala.App$class.main(App.scala:71)
    at Application$.main(Application.scala:8)
    at Application.main(Application.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)

If I do just

val jsonHeaders = """{"version123": "12.0", "method": "someMethod", "params": {"dataIds": ["12348" , "456"]}, "data2": "777"}"""
val result = Http.postData("https://someurl.com/some-url2", jsonHeaders)
        .header("content-type", "application/json")
        .header("X-Application", "myCode")
        .header("X-Application1234", "myCode2")
        .option(HttpOptions.readTimeout(10000))
println(result)

it returns

Request(POST,<function2>,<function1>,List(),List((X-Authentication,myCode2), (X-Application1234,myCode), (content-type,application/json)),List(<function1>, <function1>, <function1>),DIRECT)

What do I do wrong and is there any another simple way to send https request? Even if involves spray framework, it would be ok (I don't find any example of how to do that in spray, though).

UPDATE:

An example has been taken from here Doing HTTP request in Scala

Tidewater answered 9/6, 2013 at 6:40 Comment(3)
Looks like your second request doesn't do any actual request -- it just constructs request object, which then get triggered by asString. Are you sure that request can be fulfilled within the specified timeout (e.g. have you tried to do the same with curl).Mimas
@Mimas I can comment out the timeout and nothing will be changed at all.Tidewater
@Mimas look at my update. I can also do this request in Python and it will work well.Tidewater
D
17

You need to specify a connection timeout alongside your current read timeout with: .option(HttpOptions.connTimeout(10000)).option(HttpOptions.readTimeout(50000)). Change the 10000 to a value that works for you. The default connection timeout is a pretty aggressive 100.

You do already have a read timeout specified, but the exception says it is timing out on establishing the connection, not on the the reading of the response.

See docs: https://github.com/scalaj/scalaj-http#custom-connect-and-read-timeouts

Duplicature answered 9/6, 2013 at 15:29 Comment(4)
it didn't help. Even if I increase 60000 10 times, it seems like it turns a blind eye to it -- there is no difference at all, meaning it exists with the error so fast as before.Tidewater
maybe I confused the arguments' order?Tidewater
Weird. Just to check: you are specifying both a HttpOptions.readTimeout and a HttpOptions.connTimeout? I don't think the order should make any difference. Here is an example of how I have been using both: github.com/theon/xsbt-coveralls-plugin/blob/master/src/main/… .Duplicature
It seems to work now, it returns the empty result, though. but it does return it.Tidewater
C
0

On the HttpRequest object there is also a .timeout() member method. This method is defined as:

  /** The socket connection and read timeouts in milliseconds. Defaults are 1000 and 5000 respectively */
  def timeout(connTimeoutMs: Int, readTimeoutMs: Int): HttpRequest = options(
    Seq(HttpOptions.connTimeout(connTimeoutMs), HttpOptions.readTimeout(readTimeoutMs))
  )

The nice part about this is that it was a bit easier to mock using Mockito. See github as the reference.

Conqueror answered 4/11, 2022 at 2:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.