[Libwebsockets] LWS_CALLBACK_RECEIVE_CLIENT_HTTP

Andy Green andy at warmcat.com
Thu Oct 20 15:30:31 CEST 2016


On Thu, 2016-10-20 at 12:56 +0000, Peter Brett wrote:
> I have a quick question on LWS_CALLBACK_RECEIVE_CLIENT_HTTP. This is
> mostly out of interest, but I'd also like to check that my
> understanding of this is correct:
> 
> Looking at test-client.c, where WS data is received within
> LWS_CALLBACK_CLIENT_RECEIVE, the received data is pointed to by 'in'
> with it's length in 'len'. On receipt of HTTP data on the other hand,
> 'len' is zero and 'in' is null, so instead a call
> to lws_http_client_read is made. Is there a reason for this
> difference?

Yes... basically with the client HTTP stuff, you have contacted some
server and asked for a generic GET or POST.  Unlike the server case,
you don't really control what the remote server will insist to do.

In particular it may insist to return Transfer-encoding: chunked.  CGIs
will typically enforce returning chunked content; this is so on Apache
for example as well as lws CGI.

lws_http_client_read() automagically deals with dechunking and returns
the clean content.

Lws also has support for reverse proxying and URI content rewrite, but
this isn't plumbed in yet.  lws_http_client_read() also deals with that
processing.

> Within the call to lws_http_client_read, there appear to be recursive
> calls back into the callback, the first three of which are related to
> shared poll arrays and the last of which
> is LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ, which seems to have the
> same semantics as LWS_CALLBACK_CLIENT_RECEIVE with the received data
> pointed to by 'in'.

Yes lws_http_client_read() provides the dechunked / rewritten "clean"
data at LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ handler.

> Also is there a reason for the difference in naming convention of
> these two members of lws_callback_reason?

Naming convention?  Or the fact there's an api to get the data for http
client?

With the simple LWS_CALLBACK_CLIENT_RECEIVE, the data is buffered *and
consumed* from the pipe by the time you get the call pointing to the
buffer.  You can use the rx_flow api to pause receiving stuff like
that.

The client http stuff faces a more complicated situation where it
supports CGI, which spawns effectively three child client connections
to the script stdin, stdout, and stderr, and reverse proxy.  In both
cases the client is acting as an intermediary and has to regulate
reading from the peers according to how fast the onward connection can
take the data it's sending.  It was convenient when implementing that
to decouple the notification there was something to read from the act
of getting the buffer and consuming it.  It's more efficient to get the
notification some content is readable, schedule a callback when
WRITABLE, and in that callback send the rx buffer directly when you
read and consume it.  This minimizes the amount of transient buffered
data the user code has to deal with.

It sounds complicated but actually the dummy user callback handles
doing the right thing automatically.  In lwsws for example where only
plugins are used and there's no explicit user callback, cgi "just
works" if you configure it in JSON.  For example the mailman stuff that
runs signup for this list is using this stuff to communicate with the
CGI and return the data back synchronously, as is the git interface at
https://libwbesockets/git

-Andy

> Thanks,
> 
> Peter
> _______________________________________________
> Libwebsockets mailing list
> Libwebsockets at ml.libwebsockets.org
> http://libwebsockets.org/mailman/listinfo/libwebsockets



More information about the Libwebsockets mailing list