Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encoding of space character (" ") as "%20" vs "+" #1141

Closed
qJake opened this issue Jul 9, 2018 · 7 comments
Closed

Encoding of space character (" ") as "%20" vs "+" #1141

qJake opened this issue Jul 9, 2018 · 7 comments

Comments

@qJake
Copy link

qJake commented Jul 9, 2018

Expected Behavior

RestSharp encodes spaces in form parameters in the body as %20, +, or not at all, depending on user preference.

Actual Behavior

RestSharp encodes spaces in form parameters in the body as +.

Steps to Reproduce the Problem

  1. Create a POST request
  2. Add a body key/value parameter and include a space in the value
  3. The resulting HTTP call encodes the space character (" ") with a plus character ("+")

Specifications

  • Version: 105.2.3.0
  • Platform: ASP.NET Web Application (.NET v4.6.2)

Source Reference

querystring.AppendFormat("{0}={1}", p.Name.UrlEncode(), p.Value.UrlEncode());

Description

We are calling a third party API that requires a parameter value to be separated by spaces (e.g. VALUE1 VALUE2 VALUE3, encoded: param=VALUE1%20VALUE2%20VALUE3). When using RestSharp, the behavior of Uri.EscapeDataString() and HttpUtility.UrlEncode differs:

Uri.EscapeDataString("ABC DEF")
> ABC%20DEF
HttpUtility.UrlEncode("ABC DEF")
> ABC+DEF

RestSharp should support some manner of customization on this part, or allow the user to implement their own (optional) escape / encode / sanitize function in order to override the default behavior.

The HTTP application/x-www-form-urlencoded spec does mention that spaces should be encoded as +, however %20 also follows the spec, and not all third party systems accept + as a substitute for a space character regardless of the spec.

N.B. Is there a workaround to this in order to encode the form body as param=ABC%20DEF?

@alexeyzimarev
Copy link
Member

It would be nice if you also can come up with a suggestion for this to be fixed, or a pull request.

@shadowmint
Copy link

shadowmint commented Jul 19, 2018

I just encountered this as well, breaking against an API that only accepts '%20' not '+' for GET params on a REST call, but the root cause is identical.

The obvious solution would be to allow some kind of way to override the behavior of EncodeParameter to allow the use of EscapeDataString instead of UrlEncode

There are a number of extensive threads on stack overflow (eg https://stackoverflow.com/questions/602642/server-urlencode-vs-httputility-urlencode) about this, but it is ultimately unclear what the correct behavior actually is... and it would be very convenient to have some way to pick what you need, rather than always using UrlEncode, which is definitely not the correct behavior in some cases.

As a workaround, basically, don't use anything that set Parameters, and do it manually.

@qJake
Copy link
Author

qJake commented Jul 19, 2018

I'm thnking about the best way to implement this... probably an IParameterEncoder interface with a DefaultParameterEncoder that calls HttpUtility.UrlEncode(...) which is set as the default implementation, but can be overridden somewhere. Does it make sense to put it in RestClient, or should it go in Http like where the IWebProxy property is, here?

public IWebProxy Proxy { get; set; }

@alexeyzimarev
Copy link
Member

alexeyzimarev commented Jul 19, 2018

I think it would be easier to have it like this:

    public Func<string, string> Encoder { get; set; } = s => HttpUtility.UrlEncode(s);

I don't feel a need for an interface for a single function.

@alexeyzimarev
Copy link
Member

@qJake like this
62e95bd#diff-fbb0205ba27639004072c041141c4459R133

        /// <summary>
        /// Allows to use a custom way to encode parameters
        /// </summary>
        /// <param name="encoder">A delegate to encode parameters</param>
        /// <example>client.UseUrlEncoder(s => HttpUtility.UrlEncode(s));</example>
        /// <returns></returns>
        public IRestClient UseUrlEncoder(Func<string, string> encoder)
        {
            Encode = encoder;
            return this;
        }

@qJake
Copy link
Author

qJake commented Jan 18, 2019

@alexeyzimarev Yes! That would be fantastic. 👍

@alexeyzimarev
Copy link
Member

Will be released in the next version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants