Search code examples
javaokhttpurl-encoding

Why doesn't OkHttp encode the percent sign?


From HttpUrl.java:

static final String FORM_ENCODE_SET = " \"':;<=>@[]^`{}|/\\?#&!$(),~";

From FormBody.java

public Builder addEncoded(String name, String value) {
      names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, true, false, true, true, charset));
      values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, true, false, true, true, charset));
      return this;
    }

A side effect here is that when we post a login form (username and password), if the password contains a '%' (percent sign), then it is not encoded and the user can not log in. Why is this character not encoded by OkHttp?

For reference, here is how we are creating the form (the map contains two strings, username and password):

public RequestBody createEncodedFormBody(final Map<String, String> content) {
        final FormBody.Builder builder = new FormBody.Builder();
        for (final Entry<String, String> contentEntry : content.entrySet()) {
            builder.addEncoded(contentEntry.getKey(), contentEntry.getValue());
        }
        return builder.build();
    }

Solution

  • Use FormBody.Builder.add() instead of addEncoded(). The encoded method assumes you’ve already encoded the input.