On Tue, 2022-05-10 at 18:13 -0400, Skylos wrote: > I'm communicating with an out of spec server which does not recognize > "+" > as a blank space in query strings - this was quite a problem as I am > passing actual filenames which I don't control and which may have > spaces in > them! > > The workaround I built was to copy format (and everything it calls) > from > URLEncodedUtils and augment to pass down the blankAsPlus value, which > I > then call explicitly by bypassing the built in encoder by sending in > a raw > encoded querystring as part of the original url string I use for my > client > retrieve/execution. > > It turns out that this function: > > private static String encodeFormFields (final String content, final > Charset > charset); > > needs to have a 'false' as the ultimate argument in the call to this > function: > > private static String urlEncode( > final String content, > final Charset charset, > final BitSet safechars, > final boolean blankAsPlus); > > There was apparently no consideration that this might be necessary > outside > this private context. It's okay. I totally understand. I also > understand > that you may not like the idea of being compatible with obviously out > of > spec servers. But - it is my philosophical assertion that as a > library > which may be used by many divers purposes, it is better to allow the > user > to do whatever he wants, rather than to be quite so opinionated about > it as > to make it impossible to bypass the blankAsPlus while encoding > > My humble suggestion as thus - allow injection of blankAsPlus boolean > external to the class. (I didn't chase *all* the format > dependencies, but > would be easy enough to do with a refactor calc or simply add a > compatibility signature) > > (this one is in UrlEncodedFormEntity.java - conform with api change > and > compatibility constructor? defer to you.) > > - public UrlEncodedFormEntity ( > - final Iterable <? extends NameValuePair> parameters, > - final Charset charset) { > - super(URLEncodedUtils.format(parameters, > - charset != null ? charset : > HTTP.DEF_CONTENT_CHARSET), > - ContentType.create(URLEncodedUtils.CONTENT_TYPE, > charset)); > - } > + public UrlEncodedFormEntity ( > + final Iterable <? extends NameValuePair> parameters, > + final Charset charset) { > + super(URLEncodedUtils.format(parameters, > + charset != null ? charset : > HTTP.DEF_CONTENT_CHARSET), > + ContentType.create(URLEncodedUtils.CONTENT_TYPE, > charset), > + false); > + } > + public UrlEncodedFormEntity ( > + final Iterable <? extends NameValuePair> parameters, > + final Charset charset, > + boolean blankAsPlus) { > + super(URLEncodedUtils.format(parameters, > + charset != null ? charset : > HTTP.DEF_CONTENT_CHARSET), > + ContentType.create(URLEncodedUtils.CONTENT_TYPE, > charset), > + blankAsPlus); > + } > > > (this one is in URIBuilder.java - conform to api change - consider > also > adding mode/flag in builder to turn this on/off? (I really like this > idea)) > > public static String encodeUrlForm(final List<NameValuePair> > params) { > - return format(params, Consts.UTF_8); > + return format(params, Consts.UTF_8, false); > } > > (These are all in URLEncodedUtils.java - pass the value down in and > default > on the public level with the old api.) > > - public static String format( > - final Iterable<? extends NameValuePair> parameters, > - final Charset charset) { > - return format(parameters, '&', charset); > + public static String format( > + final Iterable<? extends NameValuePair> parameters, > + final Charset charset) { > + return format(parameters, '&', charset, false); > + } > + public static String format( > + final Iterable<? extends NameValuePair> parameters, > + final Charset charset, > + boolean blankAsPlus) { > + return format(parameters, '&', charset, blankAsPlus); > } > > - public static String format( > - final Iterable<? extends NameValuePair> parameters, > - final char parameterSeparator, > - final Charset charset) { > + public static String format( > + final Iterable<? extends NameValuePair> parameters, > + final char parameterSeparator, > + final Charset charset, > + boolean blankAsPlus) { > Args.notNull(parameters, "Parameters"); > final StringBuilder result = new StringBuilder(); > for (final NameValuePair parameter : parameters) { > - final String encodedName = > encodeFormFields(parameter.getName(), charset); > - final String encodedValue = > encodeFormFields(parameter.getValue(), charset); > + final String encodedName = > encodeFormFields(parameter.getName(), charset, blankAsPlus); > + final String encodedValue = > encodeFormFields(parameter.getValue(), charset, blankAsPlus); > if (result.length() > 0) { > result.append(parameterSeparator); > } > > (And finally encodeFormFields itself.) > > - private static String encodeFormFields (final String content, > final > Charset charset) { > + private static String encodeFormFields(final String content, > final > Charset charset, boolean blankAsPlus) { > if (content == null) { > return null; > } > - return urlEncode(content, charset != null ? charset : > Consts.UTF_8, wwwFormUrlSafe(), false); > + return urlEncode(content, charset != null ? charset : > Consts.UTF_8, wwwFormUrlSafe(), blankAsPlus); > } > > If you'd like me to submit a pull request on this, point me to the > code > repo you're using and I'll be happy to generate one. > >
As of version 5.0 HttpClient no longer uses the old `plus as blank` encoding scheme. Project code repositories can be found at the GitHub https://github.com/apache/httpcomponents-core https://github.com/apache/httpcomponents-client Oleg --------------------------------------------------------------------- To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org For additional commands, e-mail: httpclient-users-h...@hc.apache.org