How do I receive push notifications with Indy?
I have a device that uses restful Web services and I have used its request/response functionality whereby I send it a command via HTTP GET and it responds with the appropriate XML.
I now need to use the device's pus notifications. I have tried the same approach as above whereby I supply the TIdHTTP.Get
procedure with the relevant HTTP URL and stream in which to place the response, but this doesn't seem to work. The call to Get
doesn't come back. This makes sense to me in that with push notifications you are opening an HTTP stream of communication between the device and the program and this connection will remain open for streaming until closed.
My problem though is I don't know how to get the XML from the stream if the Get
method doesn't return. It is as if the program has hung. I have tried to put the communication via GET with the device and the reading of the stream into a thread so that this can continue on its own and then my main application can just check the resultant XML but this too does not work.
I am wondering if I am over complicating this and if there is a simple solution. When I simply send a request and get a response, it works fine; it's just the push streaming that I can't get to work.
If I use the URL in Internet Explorer I can see the XML returned as well as the "busy" logo constantly running indicating that the stream is open.
I have run the command through my browser Firefox Mozilla 20.0.1 and seen what wireshark captures for the push request and response. The HTTP part is shown below:
GET /elite/notifications/stream?resume=2013-05-06T00:00:00Z HTTP/1.1
Host: 192.168.10.10
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
The request I am trying to do in Delphi is as follows:
if fEventStream = nil then
fEventStream := TStringStream.Create('');
try
TapItem.fHTTP.Get(TapItem.I2IReaderIP+'/elite/notifications/stream?resume=2013-05-01T00:00:00Z',fEventStream);
TapItem.fEventXML := fEventStream.ReadString(fEventStream.Size);
except
on e:exception do begin
ShowMessage(e.message)
end;
end;
I have also tried with TidTCPConnection
fTCPConn.IOHandler.Writeln(TapItem.I2IReaderIP+I2I_PUSH_EVENT+'2013-05-01T00:00:00Z');
While not Terminated do begin
XMLString := XMLString + fTCPConn.IOHandler.Readln;
end;
Any assistance in this matter would be appreciated.
SOLUTION
In my case simply adding the GET keyword to the beginning of the call worked. I assumed the TCP Connection component requires knowledge of what action (ie GET PUT etc) it is you wish to do, it cant read my mind, makes sense
fTCPConn.IOHandler.Writeln('GET ' + TapItem.I2IReaderIP+I2I_PUSH_EVENT+'2013-05-01T00:00:00Z');
While not Terminated do begin
XMLString := XMLString + fTCPConn.IOHandler.Readln;
end;
TIdHTTP
does not support server-side pushes at this time (and even then, there are multiple ways that server-side pushes can be implemented - which one is your REST service using?). You will have to switch to TIdTCPClient
, format and send the HTTP request manually, and then use a timer or thread to read and parse the pushed responses as needed as they arrive.
The HTTP client (TIdHTTP) in the trunk of Indy 10.6 now also supports "Server Push", if the server sends a multipart/...
response:
New TIdHTTP hoNoReadMultipartMIME flag
A new hoNoReadMultipartMIME flag has been added to the TIdHTTP.HTTPOptions property. The purpose of this flag is to specify whether TIdHTTP should read the body content of "multipart/..." responses, such as "multipart/x-mixed-replace" or "multipart/byteranges", into the target TStream or to exit immediately and let the caller read the content manually instead.
As there are many different ways to implement Server Push, this answer can be more or less helpful for a given server.
链接地址: http://www.djcxy.com/p/13344.html上一篇: 在IE 9中的Rapheal饼图渲染问题
下一篇: 如何通过Indy接收推送通知?