Cracker
Cracker

Reputation: 912

HttpWebRequest doesn't send the + (plus) char

I'm trying to send a base64 encoded data using a POST request and it contains the "+" char. When I send the request, the "+" is replaced with " " (space). Here goes the code

    public string POST(string url, string query)
    {
        HttpWebRequest hwrq = CreateRequest(url);
        hwrq.CookieContainer = Cookies;
        hwrq.Method = "POST";
        hwrq.ContentType = "application/x-www-form-urlencoded";
        byte[] data = Encoding.Default.GetBytes(query);
        hwrq.ContentLength = data.Length;
        hwrq.GetRequestStream().Write(data, 0, data.Length);
        using (HttpWebResponse hwrs = (HttpWebResponse)hwrq.GetResponse())
        {
            using (StreamReader sr = new StreamReader(hwrs.GetResponseStream()))
            {
                return sr.ReadToEnd().Trim();
            }
        }
    }

    public HttpWebRequest CreateRequest(string url)
    {
        HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(url);
        Request.UserAgent = UserAgent;
        Request.Accept = Accept;
        Request.Headers.Add("Accept-Language", AcceptLang);
        Request.AutomaticDecompression = DMethod;
        return Request;
    }

I've been tracking the "query" variable, it stays with the "+" char, but when I see the request in sniffer (Charles), the request is sent without the "+".
For example I'm trying to send

<...>zxJ+zZq<...>

and

<...>zxJ zZq<...>

is actually sent.
What am I doing wrong?
Thanks in advance.

Upvotes: 3

Views: 5170

Answers (3)

moander
moander

Reputation: 2188

Try using a different content type:

hwrq.ContentType = "text/plain";

In your example you post raw base64 data (plain text), but you tell the remote server that you are posting a url encoded query string (application/x-www-form-urlencoded). That´s why the remote server tries to url decode your base64 data, which in turn will replace + with space.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1039298

+ represents space in a query string. It looks like like your query variable that you are sending is not properly URL encoded. Unfortunately you haven't shown how you are constructing this query string variable but here's the correct way in order to ensure that all values are properly URL encoded:

var values = HttpUtility.ParseQueryString(string.Empty);
values["foo"] = "some + value";
values["bar"] = "some other value";
string query = values.ToString();
// query will equal foo=some+%2b+value&bar=some+other+value

Notice how the + sign that was originally part of the value is encoded to %2B.

If you write the following:

string query = "foo=some + value&bar=some other value";

I think you see the problem for yourself and the difference between the correct query string which is foo=some+%2b+value&bar=some+other+value.

Now this being said here's what I would suggest you in order to improve your code. You could extend the WebClient class so that it can handle cookies, like this:

public class WebClientEx : WebClient
{
    public CookieContainer Cookies { get; private set; }
    public WebClientEx()
    {
        Cookies = new CookieContainer();
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = (HttpWebRequest)base.GetWebRequest(address);
        request.CookieContainer = Cookies;
        return request;
    }
}

and now simply:

using (var client = new WebClientEx())
{
    client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0";
    client.Headers[HttpRequestHeader.AcceptLanguage] = "en-us,en;q=0.5";
    var values = new NameValueCollection
    {
        { "foo", "some value" },
        { "bar", "some & other + value =" },
    };
    byte[] buffer = client.UploadValues("http://www.example.com", values);
    string result = Encoding.UTF8.GetString(buffer);
}

See how much easier this is instead of messing around with all those HttpWebRequests, responses, streams, encodings, etc...?

Upvotes: 10

Guffa
Guffa

Reputation: 700670

The form data is sent URL encoded, and a space is encoded into a +, so a + will be decoded into a space.

Use the Server.UrlEncode method to encode the data that you want to send.

Upvotes: 1

Related Questions