Here are the steps for establishing a httpConnection involved as I
see it :
* Convert String to an URI
* Convert URI to a channel
* QI the channel into a HTTPChannel using the nsIHttpChannel
* Creat an inputStream through the nsIStringInputStream interface
* Set the uplad stream of the http channel to be this new input stream
* Create a stream listener for the channel
- Implement the onStartRequest, onDataAvailable , onStopRequest ,
onChannelRedirect ,getInterface , onProgress , onStatus , onRedirect
and QueryInterface
- Specify a callback function for this listener
* open channel using the 'asyncOpen' function call.
While the above steps work fine for making asynchronous http
requests , I'm stuck with figuring out how to make synchronous
requests. I gather it isn't as simple as replacing the asncOpen
function call with a 'open' function call.
I'm providing my code below , if it helps. Thanks for your help. I'm a
noob at JS programming so please don't cuss me if my code sucks :D
(would appreciate knowing why it sucks though).
/*
What I want to do is, when the initialise function is called, I want
the result of the http request to be stored in the returnString
variable rather than be sent to the CallBack function
*/
function initialise()
{
var aData = 'sampleData';
var aMethod = "Post" ;
var aContextType = "application/x-www-form-urlencoded" ;
var hc = new HttpConnection('http://localhost:8080/cgi-bin/
hello.cgi');
var returnString = hc.sendData(aData,aMethod,aContextType);
}
function HttpConnection(aUrlString)
{
this.url = aUrlString ;
var uri = _stringToUri(aUrlString) ;
this.channel = _uriToChannel(uri) ;
}
HttpConnection.prototype.getUrlString = function()
{
return this.url ;
}
HttpConnection.prototype.sendData = function(aData,aMethod,
aContextType)
{
var httpChannel = _makeHttpChannel(this.channel);
var inputStream = Components.classes["@mozilla.org/io/string-input-
stream;1"]
.createInstance(Components.interfaces.nsIStringInputStream);
inputStream.setData(aData,-1);
httpChannel.requestMethod = aMethod;
httpChannel.setUploadStream(inputStream,aContextType, -1);
httpChannel.requestMethod = aMethod;
var listener = new StreamListener(callBack);
httpChannel.asyncOpen(listener, null);
}
function _stringToUri(aUrlString)
{
var ioService = Components.classes["@mozilla.org/network/io-service;
1"]
.getService(Components.interfaces.nsIIOService);
var uri = ioService.newURI(aUrlString, null, null);
return uri ;
}
function _uriToChannel(aUri)
{
var ioService = Components.classes["@mozilla.org/network/io-service;
1"]
.getService(Components.interfaces.nsIIOService);
var channel = ioService.newChannelFromURI(aUri);
return channel ;
}
function _makeHttpChannel(aChannel)
{
var uploadChannel =
aChannel.QueryInterface(Components.interfaces.nsIUploadChannel);
var httpChannel =
uploadChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
return httpChannel ;
}
function StreamListener(aCallbackFunc) {
this.mCallbackFunc = aCallbackFunc;
}
StreamListener.prototype = {
mData: "",
onStartRequest: function (aRequest, aContext) {
this.mData = "";
},
onDataAvailable: function (aRequest, aContext, aStream,
aSourceOffset, aLength) {
var scriptableInputStream = Components.classes["@mozilla.org/
scriptableinputstream;
1"].createInstance(Components.interfaces.nsIScriptableInputStream);
scriptableInputStream.init(aStream);
this.mData += scriptableInputStream.read(aLength);
},
onStopRequest: function (aRequest, aContext, aStatus) {
if (Components.isSuccessCode(aStatus)) {
this.mCallbackFunc(this.mData);
} else {
this.mCallbackFunc(null);
}
httpChannel = null;
},
onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
httpChannel = aNewChannel;
},
// nsIInterfaceRequestor
getInterface: function (aIID) {
try {
return this.QueryInterface(aIID);
} catch (e) {
throw Components.results.NS_NOINTERFACE;
}
},
onProgress : function (aRequest, aContext, aProgress, aProgressMax)
{ },
onStatus : function (aRequest, aContext, aStatus, aStatusArg) { },
onRedirect : function (aOldChannel, aNewChannel) { },
QueryInterface : function(aIID) {
if (aIID.equals(Components.interfaces.nsISupports) ||
aIID.equals(Components.interfaces.nsIInterfaceRequestor) ||
aIID.equals(Components.interfaces.nsIChannelEventSink) ||
aIID.equals(Components.interfaces.nsIProgressEventSink) ||
aIID.equals(Components.interfaces.nsIHttpEventSink) ||
aIID.equals(Components.interfaces.nsIStreamListener))
return this;
throw Components.results.NS_NOINTERFACE;
}
};
function callBack(x)
{
alert(x);
}
Why do you think it's more complicated than that?
Well, primarily because it didn't work :) I gathered the open method
returns an nsIInputStream and I need to read its contents to look at
the data. I tied to do that but failed and was not too sure if that
was the right thing to do. Reading output data from an input stream
didn't sound like i was on the right track.
Could you give me a few pointers on reading data from an
nsIInputStream ? The data returned by the HTTP request may be either
XML or text .
Sorry if my question is trivial.
I'm not sure what you mean with "output data", but input streams are the
only kinds of streams you can read from. That's basically their definition.
> Could you give me a few pointers on reading data from an
> nsIInputStream ? The data returned by the HTTP request may be either
> XML or text .
So in JS this is slightly harder than in C++, but it's basically like
this: (note that the code as I write it here is not very i18n-friendly,
and would also fail for binary data)
var stream = channel.open();
var scriptableInputStream = Components.classes["@mozilla.org/
scriptableinputstream;
1"].createInstance(Components.interfaces.nsIScriptableInputStream);
scriptableInputStream.init(stream);
var data = "";
do {
var str = scriptableInputStream.read(1024);
data += str;
} while (str.length > 0);
--
All the world's a stage,
And all the men and women merely players:
They have their exits and their entrances;
And one man in his time plays many parts, [...] --W. Shakespeare
That was great, thanks !