Issue #044 [Accepted/open] - Java (partly Python) client improvement possibilities

Posted by andreas.riegg

Add parameter configuration possibilities to HttpURLConnection:

// Timing parameters urlConnection.setReadTimeout(...); urlConnection.setConnectTimeout(...);

// Sometimes needed for POST, some HTTP servers complain if nothing is // posted (like webiopi does) but content-type is unset urlConnection.setRequestProperty("Content-Type", "text/plain");

// Avoid zipping
urlConnection.setRequestProperty("Accept-Encoding", "identity");

// Cache management urlConnection.setUseCaches(false);

Add HTTP (and maybe CoAP) response handling management possibilities:

// Error handling urlConnection.getResponseCode(); urlConnection.getResponseMessage(); // allow direct JSON response switching by detecting response mime type urlConnection.getContentType();

Put those values into a RestResponse Object that may also contain the response result itself.

Java (partly Python) client lacks:

Hope that helps just as a proposal list.

Andreas


Comment 1

Posted by trouch

I don't see the need except with proxied requests for this ones : urlConnection.setRequestProperty("Content-Type", "text/plain"); urlConnection.setRequestProperty("Accept-Encoding", "identity");


Comment 2

Posted by andreas.riegg

When establishing a connection with my Android App to Webiopi from External using a OpenVPN Connection via GSM or 3G I got timeout exceptions from the HTTP/Socket layer. It looks that in this case the time needed to connect and sometimes read the sockets through the VPN tunnel is too long for the default values of Android.

Adding the possibility to set the Timeout parameters and using appropriate values solved the problem. Thats the reason why I added the possibility to set the timeout values for the UrlConnection. In my app these values are then set via preferences to allow fine-tuning when needed.

The extended response handling allows me to deal with errors and manage the response switching between plain text and JSON.


Comment 3

Posted by trouch

no problem about timeout, totally understand. I asked about HTTP request headers Content-Type and Accept-Encoding


Comment 4

Posted by andreas.riegg

Concerning ("Accept-Encoding", "identity"):

This a excerpt from the description of java.net HttpURLConnection:

> By default, this implementation of HttpURLConnection requests that servers use gzip compression. Since getContentLength() returns the number of bytes transmitted, you cannot use that method to predict how many bytes can be read from getInputStream(). Instead, read that stream until it is exhausted: when read() returns -1. Gzip compression can be disabled by setting the acceptable encodings in the request header:

urlConnection.setRequestProperty("Accept-Encoding", "identity"); <<<<<

As I was not sure if the Python BaseHttpServer handles gzip handling correct (or at all) I wanted to avoid this problem by just disabling it. As in most cases the amount of data exchanged via webiopi rest calls is very small gzip compression may just be an overhead.

Concerning ("Content-Type", "text/plain"):

I encountered some http response errors when doing POST calls which do not POST content in the case of webiopi rest calls. Looks like some HTTP servers either need a POSTed content to try auto-discovery of the posted content or a Request-Header set appropriately so that auto-discovery is unnecessary. Seemed that if there is no content and no content-type request header they have a potential problem with this POST call. But I cannot remember exactly which kind of HTTP server it was at the time I tested it, maybe it was the NanoHTTPD for Java which I also used for testing some times and not the webiopi Python server.

So just keep this one as a backed-up possible solution if anyone else may encounter this kind of problem.

Andreas


Comment 5

Posted by trouch

Ok I see the problem with gzip and need for Accept-Encoding header. For the content-type one, this is certainly due to NanoHTTPD POST handling like you say. I will certainly check this and make changes this week.


Comment 6

Posted by andreas.riegg

Eric,

in the last days I read much details about Hadoop components family and its Java implementation (has nothing to do with my Raspi work). Looking how Hadoop is implemented I came across the way its configured at runtime. Aside other things it uses a Configuration class that allows dynamic configuration at runtime of many things. I found this an interesting approach that may also be of value for the Java Webiopi client package.

The way would be:

Later within a Webiopi Android client app framework package a subclass could be added to read settings from a set of predefined (by pref keys) Android preferences.

Andreas


Comment 7

Posted by andreas.riegg

As additional information these are the classes I mean:

https://hadoop.apache.org/docs/current/api/org/apache/hadoop/conf/Configuration.html https://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapred/JobConf.html

To start, just some methods would be sufficient like

public void setInt(String name,int value) public void set(String name, String value) public String get(String name, String defaultValue) public int getInt(String name, int defaultValue)

The first arguments are the parameter identifiers. According to the examples in class JobConf they could be like

webiopi.http.connecttimeout webiopi.http.readtimeout webiopi.coap.port

Usage would be

... PiConf conf = new PiConf(); conf.setInt("webiopi.http.port", 8000); conf.set("webiopi.http.user", "webiopi"); ... PiClient client = new PiClient(conf); ...

PiConf could then have additional methods to read/write to formats like XML, webiopi config, JSON etc.

And for Android I could provide a subclass that reads/writes from Android Preferences. Nicely the keys of the Preferences could be the same as the parameter names above.

Andreas


Comment 8

Posted by trouch


Comment 9

Posted by trouch


Comment 10

Posted by trouch