Using HttpURLConnection to submit a json POST requ

2019-07-24 14:57发布

问题:

I am trying to submit a json post request using HttpURLConnection in Scala. I followed along to two tutorials and produced this:

def sendPost(url: String, jsonHash: String) {
  val conn: HttpURLConnection = new URL(url).openConnection().asInstanceOf[HttpURLConnection]
  conn.setRequestMethod("POST")
  conn.setRequestProperty("Content-Type", "application/json")
  conn.setRequestProperty("Accept", "application/json")
  conn.setDoOutput(true)
  conn.connect()

  val wr = new DataOutputStream(conn.getOutputStream)
  wr.writeBytes(jsonHash)
  wr.flush()
  wr.close()

  val responseCode = conn.getResponseCode

  println("Sent: " + jsonHash + " to " + url + " received " + responseCode)

  val in = new BufferedReader(new InputStreamReader(conn.getInputStream))
  var response: String = ""
  while(response != null) {
    response = in.readLine()
    println(response)
  }
  in.close()
}

It responds with:

Sent: '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail@thecompany.com", "async":false}' to http://localhost:4040/scheduler/iso8601 received 500 

java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:4040/scheduler/iso8601

stemming from

val in = new BufferedReader(new InputStreamReader(conn.getInputStream))

but if I rebuild it as a curl request, it works fine:

curl -X POST -H 'Content-Type: application/json' -d '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail@thecompany.com", "async":false}' http://localhost:4040/scheduler/iso8601

requirement failed: Vertex already exists in graph Scala-Post-Test

(which is what I expect)

Any insight to what is wrong? I'm trying to sniff the packets now to determine what is different.

(Note: I had previously given up on sys.process._)

回答1:

The issue is here:

Sent: '{"schedule":"R/2014-02-02T00:00:00Z/PT24H", "name":"Scala-Post-Test", "command":"which scalac", "epsilon":"PT15M", "owner":"myemail@thecompany.com", "async":false}' to http://localhost:4040/scheduler/iso8601 received 500

You'll note your JSON is surrounded by single quotes. This makes it invalid.

Also worth noting is that while this code works, you are using a DataOutputStream.writeBytes() to output your data. This would be problematic if your string including anything but single-byte characters; it strips the high 8 bits off each char (Java uses 2-byte chars to hold UTF-16 codepoints).

It's better to use something more suited for String output. The same technique you use for input, for example:

BufferedWriter out = 
    new BufferedWriter(new OutputStreamWriter(conn.getOutputStream));
out.write(jsonString);
out.close();