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

Community
  • 1
  • 1
Alan Coromano
  • 24,958
  • 53
  • 135
  • 205
  • 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). – om-nom-nom Jun 09 '13 at 07:45
  • @om-nom-nom I can comment out the timeout and nothing will be changed at all. – Alan Coromano Jun 09 '13 at 09:04
  • @om-nom-nom look at my update. I can also do this request in Python and it will work well. – Alan Coromano Jun 09 '13 at 09:14

2 Answers2

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

theon
  • 14,170
  • 5
  • 51
  • 74
  • 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. – Alan Coromano Jun 09 '13 at 16:36
  • maybe I confused the arguments' order? – Alan Coromano Jun 09 '13 at 16:38
  • 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: https://github.com/theon/xsbt-coveralls-plugin/blob/master/src/main/scala/com/github/theon/coveralls/CoverallsClient.scala#L48 . – theon Jun 09 '13 at 22:44
  • It seems to work now, it returns the empty result, though. but it does return it. – Alan Coromano Jun 10 '13 at 05:00
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.