Jetty client POST file to Jetty Server - jetty

I'm creating a Jetty client that will POST files to a Jetty Server. I'm trying to use the ContentExchange.setFileForUpload(), but I'm not able to find any example code on the web on how to use this API properly.

The API is self-explanatory, just pass in the file that you want to upload; the rest is just basic HTTP:
HttpClient httpClient = ...;
File file = ...;
ContentExchange exchange = new ContentExchange(true);
exchange.setURL("http://host/path");
exchange.setMethod(HttpMethods.POST);
exchange.setFileForUpload(file);
exchange.setRequestHeader("Content-Type", "application/octet-stream");
exchange.setRequestHeader("Content-Length", String.valueOf(file.length()));
httpClient.send(exchange);
// Wait for the upload to complete
exchange.waitForDone();
Look at the HttpClient documentation if you want better control on the HTTP phases the file upload will go through, or better yet switch to Jetty 9's HttpClient, which is a vastly improved implementation.

Related

Add cookie to HTTP header for SOAP call in ColdFusion

I basically want to add the ASP.NET_SessionId cookie to my HTTP request header when calling a SOAP web service through ColdFusion.
The web service is registered in the OnApplicationStart function of the Application.cfc component in ColdFusion.
<cfscript>
objSoapHeader = XmlParse("<wsse:Security mustUnderstand=""true"" xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""><wsse:UsernameToken><wsse:Username>MY_USERNAME</wsse:Username><wsse:Password>MY_PASSWORD</wsse:Password></wsse:UsernameToken></wsse:Security>");
Application.UserWebService = CreateObject("webservice","MY_URL/UserService.asmx?WSDL");
addSOAPRequestHeader(Application.UserWebService,"","",objSoapHeader,true);
</cfscript>
My web service is called as such:
<cfset Result = "#Application.UserWebService.SomeFunction("1", "DATA")#">
In order for the .Net server (where the web services are located) to remember my session state, I must pass the ASP.NET_SessionId cookie in the HTTP request header, but have no idea if this is even possible in ColdFusion.
I've researched for several hours but nothing has come of it as of yet, so has anyone successfully managed to pull this off?
Short Answer:
For CF9 / Axis1 try enabling sessions on the web service object.
ws = createObject("webservice", "http://localhost/MyWebService.asmx?wsdl");
ws.setMaintainSession( true );
For CF10+ / Axis2, see longer answer below:
(Disclaimer: Using cfhttp might be simpler, but I was curious and did some digging ..)
From what I have read, since CF10+ uses Axis2 for web services it should be possible to use the underlying methods to maintain session state through HTTP cookies.
How to set Cookies in ColdFusion SOAP requests - (circa 2006) - Written for a much older version of CF/Axis, so some of it is outdated, but it still provides a good overview of the general concept.
Maintain session in Axis2
Java axis web service client setMaintainSession on multiple services (cookies?)
Axis2 Manage Session Cookie Manually
Using the the links above, I put together a quick POC using a basic web service and was able to extract the cookie header from the web service client response:
// make initial request
ws = createObject("webservice", "http://localhost/MyWebService.asmx?wsdl");
ws.firstMethod();
// For maintainability, use constants instead of hard coded strings
wsdlConstants = createObject("java", "org.apache.axis2.wsdl.WSDLConstants");
// Extract headers
operation = ws._getServiceClient().getLastOperationContext();
context = operation.getMessageContext( wsdlConstants.MESSAGE_LABEL_IN_VALUE );
headers = context.getProperty( context.TRANSPORT_HEADERS );
Then set the cookie and instruct the web service client to send it with subsequent requests:
if ( structKeyExists(headers, "Set-Cookie") ) {
// include http cookies with request
httpConstants = createObject("java", "org.apache.axis2.transport.http.HTTPConstants");
options = ws._getServiceClient().getOptions();
options.setManageSession( true );
options.setProperty( httpConstants.COOKIE_STRING, headers["Set-Cookie"] );
}
// ... more requests
ws.secondMethod();
ws.thirdMethod();
NB: Side note, I noticed you are storing the instance in the shared Application scope. Just keep in mind web service instances are probably NOT thread safe.
Inside your CFHPPT tags, set the cookie with CFHTTPPARAM

Can Casablanca be used as a webserver to serve assets?

Does Casablanca (Microsoft's C++ REST SDK) be used to serve web assets (html, images, js, css, etc)?
I built a REST server with Casablanca, and for the specific REST stuff it works great. But how do I serve a full site?
Do I have to run nginx/apache in parallel to my REST server to serve assets, or build some simple file webserver with boost.asio, etc?
I am targeting an embedded system and thus want to keep a low resources demand, so ideally Casablanca it self could serve my assets as well as my routes.
You probably won't want to do that with Casablanca. It's intended for use as a REST endpoint server. It's possible, but it makes more sense to use an instance of Apache/Tomcat to serve a website.
That being said, it is possible. You can give it a try by doing something like the following in your GET Handler:
void HandleGet( http_request Message) {
utility::string_t body =
"<html><body>"
"<h1>Hello World!</h1>"
"</body></html>";
Message.reply( status_codes::OK, body, L"text/html");
}

How to disable chunking in cxf webservice on server-side?

I need to disable chunking in cxf webservice on server-side as some clients need 'Content-Length' header in response. Now i can see 'Transfer-Encoding' is 'chunked' in server response and no 'Content-Length' header is sent.
I've found that chunkins can be disabled in spring's context like this:
<http-conf:conduit name="*.http-conduit">
<http-conf:client ReceiveTimeout=“300000“ AllowChunking="false"/>
</http-conf:conduit>
Since i'm creating services programmatically like this:
// media service
Object mediaService = new MediaService();
System.out.println("Starting media service #1 ...");
EndpointImpl mediaEP = (EndpointImpl)Endpoint.create(mediaService);
mediaEP.publish("http://localhost:8081/onvif/media_service");
How can i do it?
Actually, you can't easyly specified to not allow chuncking from server side.
Indeed, it's a client pb! What I understand is that you have a client of your ws who can't modify his code to desactivate chunking?
You have to do that : write a CXF interceptor that would replace the servlets OutputStream in the message with a buffer of some sort (ByteArrayOutputStream or CachedOutputStream) at the beginning of the output chain and then at the end of the chain, use that to set the Content-Length header on the response and copy that data to the real output stream.
Indeed, the content lenght will force the framework to not use the chunking.
I did it once before. I'll try to post you maybe tomorrow a code of such interceptor.

Stub generated using Axis2 Webservice forming new connection for redirect URL...Need same TCP connection...!

I am badly stuck with a SOAP based integration using Axis2 framework for generation of client stubs from the Server WSDL. The scenario is as follows :
There is always a login API call first, which gives a Success response in SOAP body and Temporary Redirect in HTTP header. Also provides a URL which contains the session ID in the Location field of HTTP Header.
The next API call is required to be made at this redirect location. IN THE SAME TCP CONNECTION, for getting a proper response.
Now, the problem is, as a part of Webservice implementation using Axis2 generated stubs, I need to reload this redirect URL and re-instantiate it as --- "stub=new Stub(newurl)"
As soon as this is done, it creates a new TCP connection and so, the next request gives the response as "session ID invalid" because it goes out-of-sync with login API.
I have tried everything mentioned as a solution in this forum and nothing is working out.
For e.g --
MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
HttpClient httpClient = new HttpClient(httpConnectionManager);
ServiceClient serviceClient = stub._getServiceClient();
Options opts = stub._getServiceClient().getOptions();
opts.setTo(new EndpointReference(prop.getProperty("target_end_point_url")));
opts.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
opts.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
serviceClient.setOptions(opts);
stub._setServiceClient(serviceClient);
Similarly, I have tried many other options too. But it's not helpful at all.
Faced exactly the same issue.
Following steps solved the issue.
1. Using HttpClient, perform login. Don't use stub object to perform login.
2. Use the Location Header URL, to create new stub object i.e. stub = new Stub(locationURL). (Your existing options setting should be retained.)
3. There is a default timeout, by which server disconnects the TCP connection. In my case it was 50 seconds. Hence as soon as i performed login in step 1, i execute a timer every 40 seconds, to send an empty requests to new Location URL using HeadMethod of same HttpClient object.

Setting HTTP headers through Axis2 API

I am using apache axis2 server webservies, Basically I am sending xml response to android client through webservices. Here I need to maintain the session since the services per user basis. I know maintaining session in webservices is bad idea, but cant avoid it.
Actually I need to generate random unique string when user invoke first service from android client, that random string going to be used as session id. This session id, i need to set in http custom header, so that android client can able to get it and can send it subsequent requests as well.
I want to know whether any API is available in axis2 to set custom header information on http headers. Same way I need to read the http header, so that next request I can get the session id from header.
Can anyone advice me regarding this?? Thanks
-Ravi
Dead link on #Martin Dürrmeier's answer, here's a snapshot of the webpage that i've found on web.archive.org : Axis2 - Setting custom HTTP Headers on a response, it helped me.
Here's the lines needed :
MessageContext responseMessageContext =
MessageContext.getCurrentMessageContext().getOperationContext().getMessageContext(
WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
List<Header> headers = new ArrayList<Header>();
headers.add(new Header(HTTPConstants.HEADER_CONTENT_ENCODING, "identity"));
responseMessageContext.setProperty(HTTPConstants.HTTP_HEADERS, headers);