3

I'm working on a J2ME application that uses HTTP GET requests to communicate with a server. I already have a method to generate URL encoded parameters.

In its present form it can not cater for empty strings,other code snippets I've seen have this deficiency as well, because they all rely on comparing the individual characters of a string argument.I have previously asked a question related to this empty char dilemma

EDIT:

Requests to the server (Play 1.0) are in the form

http://server.com/setName/firstname/othername/lastname

Parameters cannot be null so http:server.com/setname/firstname//lastname is invalid

The parameters are retrieved from a json object.Currently the url encoding method I have will encode all the extracted parameters correctly and leave any character which cannot be converted as is.A space in a string as in "Jo e" and space character itself will be encoded as Jo%20e and %20 respectively. The JSON object

{ "firstname":"joe"
  "othername":""
  "lastname":"bloggs"
}  

will however result in the invalid url http://server.com/setname/joe//bloggs because the othername parameter is an empty string and is left as such by my method.

I could check that the string about to be returned is empty and return a space character instead. But I'm wondering if there isn't a better modification to this method or a whole new approach which would be more robust?

 public static String urlEncode(String s) {
    ByteArrayOutputStream bOut = null;
    DataOutputStream dOut = null;
    ByteArrayInputStream bIn = null;
    StringBuffer ret = new StringBuffer();
    try {
        bOut=new ByteArrayOutputStream();
        dOut = new DataOutputStream(bOut);
        //return value
        dOut.writeUTF(s);
        bIn = new ByteArrayInputStream(bOut.toByteArray());
        bIn.read();
        bIn.read();
        int c = bIn.read();
        while (c >= 0) {
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '*' || c == '_') {
                ret.append((char) c);
            } else if (c == ' ' ) {
                //ret.append('+');
                ret.append("%20");
            } else {
                if (c < 128) {
                    appendHex(c, ret);
                } else if (c < 224) {
                    appendHex(c, ret);
                    appendHex(bIn.read(), ret);
                } else if (c < 240) {
                    appendHex(c, ret);
                    appendHex(bIn.read(), ret);
                    appendHex(bIn.read(), ret);
                }
            }
            c = bIn.read();
        }
    } catch (IOException ioe) {
        System.out.println("urlEncode:"+ioe);
        return s;
    }
       return ret.toString();
}

private static void appendHex(int arg0, StringBuffer buff) {
    buff.append('%');
    if (arg0 < 16) {
        buff.append('0');
    }
    buff.append(Integer.toHexString(arg0));
}
Community
  • 1
  • 1
jgatcher
  • 175
  • 5
  • 12
  • "it however does not/can not cater for empty strings" - what *exactly* do you mean by this? Where precisely do empty strings cause an issue, and what is that issue? Is there an exception/crash, or do you just get unexpected/undesired behavior? – yoozer8 Aug 23 '12 at 14:04
  • Are all of the parameters required? Is there one optional parameter, or could there be several? – yoozer8 Aug 23 '12 at 15:14

1 Answers1

5

According to RFC 1738, there is no URL encoding of an empty character. This leaves you with four options.

  1. Require that all the fields be populated. This might not be a good choice, depending on what your application does, since users may not have data for a particular field, or prefer not to share it.

  2. If there is only one field that could allowably be blank, re-order the URL parameters such that it is last. This will result in /joe/bloggs/ rather than /joe//bloggs.

  3. If a URL could potentially have more than one empty parameter, it would be best to use a querystring. This would look like /setName?firstname=joe&othername=&lastname=bloggs. Non-used parameters could be left out or included.

  4. Use POST instead of GET. Simply use the url /setName and put all of the fields in to a form. Based on the URL, the action apparently being performed seems more suited to a POST than a GET anyway.

yoozer8
  • 7,361
  • 7
  • 58
  • 93
  • I probably should have added that I am only working on the client side so i'm not at liberty to make the changes suggested.That's why my focus is on being able to detect empty strings and replace them with a legal character like space – jgatcher Aug 23 '12 at 16:43
  • Is the server side currently under development, or is it already built? – yoozer8 Aug 23 '12 at 16:45
  • the server side has already been built and ,ade public to other developers – jgatcher Aug 24 '12 at 05:54
  • 1
    Then you should check with the developer/documentation for the server side to see how such situations should be handled. If there is no clear explanation, and it doesn't specify that all fields are mandatory, file a bug report about non-required fields breaking the URL if they are not provided. – yoozer8 Aug 24 '12 at 12:48