How to PUT/POST with specific Mime content-type?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to PUT/POST with specific Mime content-type?

LouisJB
Hi,

got a simple bit of test code to perform some post compile/package/deploy testing of some web services.

With some really simple test code to attempt to put some text/xml to a web service like this and then display / validate the response:

http((req / "resource/0" <<< body) >>> System.out)

where body is : scala.xml.Elem

it appears what is sent is:

"Content-Type: text/plain; charset=UTF-8[EOL]"

With a body with containing what appears to be the right content.

but what I want to do is specify it as text/xml, i.e.

"Content-Type: text/xml; charset=UTF-8[EOL]"

What is the best way to achieve this for HTTP put/post requests? Probably obvious(?) but I can't find any documentation or examples that cover this.

thanks in advance, Louis
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

n8han
Administrator
Pretty obvious, but not implemented yet. :) There is such an interface for files but not for Strings. From dispatch/Http.scala:

  /** Put the given object.toString. (new request, mimics) */
  def <<< (body: Any) = next {
    val m = new HttpPut
    m setEntity new StringEntity(body.toString, defaultCharset)
    HttpProtocolParams.setUseExpectContinue(m.getParams, false)
    Request.mimic(m)_
  }
  /** Put the given file. (new request, mimics) */
  def <<< (file: File, content_type: String) = next {
    val m = new HttpPut
    m setEntity new FileEntity(file, content_type)
    Request.mimic(m) _
  }

I'll add an interface for Strings with content_type for 0.7.3, but if you want it now you can implement it directly similar to the way this worked for posting XML:
http://n2.nabble.com/How-to-POST-XML-tp4457822p4458472.html

Also you could add the operator more nicely thru implicit extension, but I'm not sure that's worth the trouble since I'll definitely be adding it to the base Request class in the next version.

Nathan
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

LouisJB
Hi Nathan,

thanks! - I was just browsing the source and coming to a similar conclusion, except that I notice that Dispatch is pulling in Apache HTTP core 4.01 and for StringEntity there is no constructor to specify content type until the newer 4.1 (still in alpha currently by the looks of it).

Anyway, sure this can be worked around, or maybe by using an underlying stream/bytearray instead.

Here is except from that Apache API:

--
StringEntity

public StringEntity(String s,
                    String mimeType,
                    String charset)
             throws UnsupportedEncodingException
Throws:
UnsupportedEncodingException
Since:
4.1

--
 
In the mean time I was experimenting and found another kind of hacky work around which might do the trick (well it's working!) until a new version of the library is available.

Basically construct a new request with header added for content type explicitly

val http = new Http
val req = :/("localhost", 8080) / "some/fantastic/resources"

import collection.immutable.{Map => IMap}

val xmlReq = req <:< IMap("Content-Type" -> "text/xml")

http(((xmlReq / "resource/0") <<< body) >>> System.out)

so, this does appear to do the trick but is hopefully just very temporary...

When do you envisage next version of the library and will you intent to update to Apache http core/client 4.1 if released in time?

thanks very much,

Louis
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

n8han
Administrator
That's interesting, that HttpClient allows your header to override the one that StringEntity would send.

I was thinking that I might just do a quick release today for this, but that was under the incorrect assumption that I could just pass the content-type to StringEntity in 4.0. Bummer.

There's some other stuff I want from the 4.1 line, but not enough to depend on alpha releases. Might be worth making the changes on a branch tho, just so they aren't forgotten.

Nathan
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

LouisJB
Hi,

Yes, I'm not quite sure how that was implemented in HttpClient using 4.01 (without looking at the source code) but presume a string is coerced into some other structure under the hood, that allows content type to be set.

Anyway, be great to have a solution for this. I'm happy to use my simple work around for now until a new version is available.

On a similar note, I had to add a little helper function for HTTP Delete method, such as:

def delete(req: dispatch.Request) = req.next {
    val m = new HttpDelete
    Request.mimic(m) _
  }

and use like this:

http(delete(xmlReq / "res" / id.toString) <> { rsp =>
    ...
})

which is fine, but (unless I've overlooked it) I can't see an "operator" for delete directly like there are for put, post and get methods - is this something done on purpose or will it be added in the next version perhaps?

Operating on RESTful web services (I'm using this library for functional testing of web services) the full set of http methods and the ability to set the content type forms the bare essentials needed to send the right commands to exercise web services, in terms of CRUD operations. I'm glad to have it all working already, but it sure would be nice to be able to remove these workarounds when the next version is available.

Thanks for the help,

Louis
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

n8han
Administrator
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

LouisJB
Regarding DELETE - ahah you're right, I do apologise. I'd seen that but not realised it could be used directly from client code. Tried it, it's all working nicely, thanks! :)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to PUT/POST with specific Mime content-type?

Mats Johnson
In reply to this post by n8han
Hi, seems like this hasn't happened yet, or is there some other, better way now?
Loading...