Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I cater for empty strings while encoding parameters for a GET request?

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));
}
like image 938
jgatcher Avatar asked Dec 13 '25 05:12

jgatcher


1 Answers

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.

like image 146
yoozer8 Avatar answered Dec 16 '25 06:12

yoozer8