Using IdHTTP to send array of bytes to a PHP - delphi

I am trying to build a simple client - server - client application using the IdHTTP component.
How to use IdHttp component to send array of bytes from a client1 to a php file located on www.example.com and have this php file send the same data to be consumed by a client2 using the IdHTTp? Maybe I am taking the wrong path here.

For sending the data from client1 to the server I recommend to use Base64 encoding. This way you have a normal string instead of a byte array. Sending strings with IdHTTP is simple. An alternative is multipart form data (Java code here).
For receiving the data on client2: HTTP clients do not know when there is data on the server. Asynchronous receive (server push) is a feature of the new WebSocket protocol, which is an extension of HTTP so it needs specifix extensions on the client and server side. There are open source and commercial implementations of the WebSocket protocol for Delphi.
If your client2 is a normal HTTP client, it has no option than to continuously poll data from the server. For basic use cases, I would recommend a TIdTCPClient component instead of TidHTTP which gives you more control over the processing of incoming data. The client jst needs to open a socket connection on port 80 of the server, send a well-formed HTTP request and then run a loop to receive the response. When the server has new data, the PHP script will start to send data (maybe even without HTTP response headers) and then the Base64 encoded data.

Related

What is the difference between a request and a command?

Just a simple question:
what is the difference between a request and a command in protocols like HTML or SMTP?
Can it be that requests await a response?
Or that one is from the client side and the other from the server side?
Thanks in advance!
Similar to http, smtp requests can contain multiple commands e.g. the TLS command to enabled encryption
E.g. HELO, BYE
Ftp is similar to Smtp, where a single connection (request) exchanges multiple commands (PASV... EXIT) before the connection is closed.
The main difference is the request response for http can usually be visualized as 1 request to 1 response however when you look at how the TLS encryption is applied over http you then see similar commands being exchanged between client and server before the final response is returned to the client.
In short http separates the noise of the commands by encompassing them into the header portions of the request and response.
An example of http commands without encryption would be chucked transfer encoding where the server send a part of the response after the headers in chunks which must be put back together at the client side.

How do I retrieve a complete HTTP response from a web server including response body using an Indy TIdTCPClient instance?

I have a Delphi 6 application that uses an Indy TIdTCPClient instance to communicate with a web server. The reason I am not using an HTTP client directly is because the the server is an image streaming server that uses the same socket connection for receiving the command to start streaming as it does to start "pushing" images back to you. In other words, after you send it a typical HTTP POST request, it replies with an HTTP response, and immediately after that it starts sending out a stream of JPEG images.
I already know how to craft a proper POST request and send it using the TIdTCPClient WriteBuffer() method and then use the ReadBuffer() method to receive reply data. What I'd like to do instead is to send a POST request and then ask Indy to wait for a typical HTTP response including retrieving all the bytes in the response body if there is a Content-Length header variable. I of course want it to leave the JPEG frames intact that may have piled in after the HTTP response in the receive queue until I start requesting them (that is, I don't want it including any of the JPEG frames in the HTTP response to my streaming request command until I ask for them using a successive read call).
Is there a method that I can call on a TIdTCPClient that will retrieve completely a typical HTTP response with body content, and nothing else? I thought about using SendCmd() and checking the LastCmdResult property (type: TIdRFCReply) for the response, but I can't tell from the Indy documentation if it retrieves the response body content too if there is a Content-Length header variable as part of the response it returns, nor can I tell if it leaves the rest of the receive queue after the response intact.
What is the best way to accomplish this mixed mode interaction with an HTTP web server that pushes out a stream of JPEG frames right after you make the HTTP request to start streaming?
Also, if there is a clever way to have Indy split the frames using the JPEG frame WINBONDBOUDARY delimiting string, rather than accumulating blocks of data and parsing them out myself, please share that technique.
The correct way to read an HTTP response is to first read the CRLF-delimited response headers line-by-line until a blank line is encountered, aka a CRLF+CRLF sequence, then you can use those headers to decide how to read the remaining response data. The headers will tell you not only what kind of stream is being sent (via the Content-Type header), but also how the data is being framed (Content-Length, Transfer-Encoding: chunked, something specific to the particular Content-Type, etc).
To receive the headers, you can use the connection's Capture() method, setting its ADelim parameter to a blank string.
How you read the remaining data afterwards depends on the actual formatting/framing of the stream. Without knowing exactly what kind of stream you are receiving, there is no way to advise you how best to read it, as there are several different types of streaming protocols used by HTTP servers, and most of them are not standardized. Provide that information, then I/we can show you how to implement it with Indy.
You cannot use SendCmd() as the HTTP protocol does not format its responses in a way that is compatible with that method.

Preference of HTTP Server

I am trying my hand in server applications using Indy Internet tools.
My client sends Post data (XML) in Unicode format.
Can I convey my preference to client (HTTP Client). I prefer Text. In general can a HTTP server send its preferences to its Clients?
Thanks for any hint or help.
The problem with this is the fact, that with only one POST the server has no way to respond, until the client has already sent the data.
The solution is to make two calls: One where the client asks for the server preferences and another to send the data. The OPTIONS HTTP method can be used for this scenario.
You can handle both requests on the same URL: If the clients makes an OPTIONS request the server responds with the configuration data. (via response headers) Then the client can make a POST request on the same URL and the server handles the data appropriately.
For further information see HTTP methods and HTTP headers, especially the Accept header.

Transferring Data Directly between 2 Connections in Indy (TIdContext)

ive a sever running TIdTCPServer, and Client Using Web Browser (or any other software) to Communicate, i dunno the protocol, but what im trying to do is to Send The Data between the client and another Connection (Both Connected to the same TIdTCPServer) for example the data sent by the first client is transmitted to the second client, and the data sent by the second client is transmitted to the first client, like a proxy (i cant really use a proxy server since its just this one condition) and the TIdTCPServer should still be receiving other clients and processing their data.
i stumbled upon the first line of code, since TIdContext.Connection.Socket.ReadLn requires a Delimiter, and the Client's Protocol is unknown to the server.
any ideas?
thanks.
You can look at the source code for TIdMappedPortTCP and TIdHTTPProxyServer to see how they pass arbitrary data between connections in both directions. Both components use TIdSocketList.SelectReadList() to detect when either connection has data to read. TIdMappedPortTCP then uses TIdBuffer.ExtractToBytes() and TIdIOHandler.Write(TIdBytes), whereas TIdHTTPProxyServer uses TIdTCPStream and TIdBuffer.ExtractToStream() instead.

Progress feedback in stateless HTTP session

I need to program a stateless server to execute remote methods. The client uses REST with a JSON parameter to pass the method name and its parameters. After servicing the result the session is closed. I have to use Indy10, TCP/IP as protocol, and therefore look at using IdHTTPServer.
Large result sets are chunked by Indy10 and sent to the client in parts.
My problem now is:
The methods on the server provide progress information if they take longer to produce the results. These are short messages. How can I write back to the client?
So far I have used writeflush on the server, but the client waited for the request to end before handing back the full resultset, including the progress information. What can I do to display/process such progress information on the client and yet keep the connection open to receive further data on the same request?
On the client side instead of the regular HTTP client component TIdHTTP you can instead use Indy class TIdTCPClientCustom in unit IdTCPClient to send the request and process the response.
This class gives total control over the processing of the server responses. I used the TIdTelnet class as a starting point to implement a client for a message broker messaging protocol, and found it stable and reliable for both text and binary data.
In the receiving thread, the incoming data can be read up to delimiters and parsed into chunks (for the progress information) and immediately processed.

Resources