15

Regarding this line:

var data = encodeURIComponent(JSON.stringify(object_literal));

I don't understand why this is being URI encoded.

Later data will be sent via ajax POST.

I understand that URLs, particularly the one you can see in the browser address bar require special characters as described here:

http://www.blooberry.com/indexdot/html/topics/urlencoding.htm

But what exactly does this have to do with Ajax posting?

Do both the url address bar and the internal ajax post utilize the same mechanism?

mark_huffington
  • 464
  • 1
  • 3
  • 12
  • Post data is sent in the body of the http request, and get data is appended to the URL, so the mechanism is different. Why do you assume that post data needs to be uri encoded? It doesn't seem like it has to be... http://jsfiddle.net/DXWqX/ – nbrooks Aug 22 '13 at 13:32
  • That's true for get requests, which must be URI encoded. A get request is what your browser makes when you type in a URL. All it does is append the data to the url as query parameters `url?param1=value1&param2=value2`. Post requests don't do that. – nbrooks Aug 22 '13 at 13:36

4 Answers4

23

It all depends on the content type.

Normally when a <form> uses the HTTP method POST then the form values are URL Encoded and placed in the body of the request. The content type header looks like this:

content-type: application/x-www-form-urlencoded

Most AJAX libraries will do this by default since it is universally accepted among web servers. However, there is nothing preventing you from simply serializing the data as JSON or XML and then sending it with a different content type.

content-type: application/json

or

content-type: text/xml

It's worth noting that the payload has nothing to do with AJAX! Under the hood they are all using the XmlHttpRequest object to send an HTTP request asynchronously to the server. It doesn't matter if you send Plain Text, JSON, XML, or even raw binary data so long as you tell the server how to interpret those bits.

The url encoding is purely a historical artifact of how <form> elements posted their data to the server before AJAX was around.

dkretz
  • 37,399
  • 13
  • 80
  • 138
Josh
  • 44,706
  • 7
  • 102
  • 124
  • As @Josh mentioned $.ajax does this encoding by default. – Ankit Jaiswal Aug 22 '13 at 13:39
  • O.K. according to both answers, I don't need to URI encode my ajax posts. I'm removing it. – mark_huffington Aug 22 '13 at 13:44
  • @mark_huffington - Hopefully my update adds some clarity. It's simply a historical artifact of how the web worked pre-ajax. AJAX libraries did this by default simply to provide backwards compatibility with the vast majority of web sites out there because they **expected** the data to be posted in this fashion. Now it doesn't really matter as much. XHR is just a transport mechanism. It says nothing about the contents of the request. – Josh Aug 22 '13 at 13:45
  • ...this makes be believe you do have to URI encode your ajax post data...perhaps this artifact is a **required artifact** ? – mark_huffington Aug 22 '13 at 13:47
  • 1
    @mark_huffington - It is completely dependent on the endpoint. If you are posting to an endpoint that can only handle "x-www-form-urlencoded" data then it needs to be that way. If it can handle XML or JSON then you can use that. Getting it to work is 100% dependent on what the endpoint can handle. – Josh Aug 22 '13 at 13:51
  • If I remove the URI encoding and change to `content-type: application/json` what would change on the endpoint? Nothing I imagine, I would just check the POST super global (PHP) and it should be there same as before? – mark_huffington Aug 22 '13 at 13:53
  • @mark_huffington - If you want to pass it as JSON via jQuery then you will need to set the content type to `application/json` and then do a `JSON.stringify(obj)` on your data. What you will get on the other end will be a JSON string in the body of the request. If you just pass the data without any modifications, jQuery will url encode the data like it was posted by a form. In your endpoint then you will have form variables that you can read from. It's up to you how you handle it. – Josh Aug 22 '13 at 13:57
  • 1
    @mark_huffington — The POST super global is only populated by `application/x-www-form-urlencoded` and `multipart/form-data` messages. If you want to handle `application/json` data you will need to access the raw POST body and parse it yourself. – Quentin Aug 22 '13 at 13:57
  • Yes, you should set the `contentType` property on the ajax post to `'application/json'`. There is no need to URI encode the data. – Brett Aug 22 '13 at 14:10
  • @Quentin - what do you mean? "raw POST body" ... I assume this would be in `$_POST` ( for PHP ) or no? if so what key? I don't know what you mean? I'm asking b.c. I'm considering changing the way I do ajax for my app from url encoded to json encoded. – mark_huffington Aug 26 '13 at 21:52
  • `$_POST` contains key/value pairs parsed out of data submitted in the form of `application/x-www-form-urlencoded` and `multipart/form-data`. The raw POST body is what you get in the `php://input` file. – Quentin Aug 26 '13 at 22:11
  • well...I don't need such a big project, I've never used this thing `php://input` - the web is full of nonsense...like using Base64 to encode images...more wasted efficiencies b.c. of artifacts... – mark_huffington Sep 19 '13 at 12:49
  • ... and please remove the jQuery embedded in your cortex. – mark_huffington Sep 19 '13 at 12:52
6

Josh's answer is good, but I think it's missing something. Traditionally form data was posted using the same format as querystrings. eg: param1=value1&param2=value2 and the only difference between a GET and POST is that POST puts these parameters in the message body whereas a GET puts them in the URL. However, the obvious problem is that if your parameter names or values include unescaped characters like & and =, then you'll screw up the server's ability to automatically parse the parameter collection, resulting in corruption of the data. Using Javascript's encodeURIComponent() function on each parameter value will escape all these characters for you.

So bottom line: if you are not using the old standard parameter collection on the server side--for example, if you are parsing JSON instead--then there's no need to URL encode the text. Also, there's no reason to URL encode if you aren't parsing out multiple parameters on the server side so running encodeURIComponent once on the entire message body makes no sense.

Side note: if you are using asp.net and trying to let users pass html to the server, encodeURIComponent will let you do this without disabling the request validation that normally prohibits this. I don't think sending it as JSON, alone, would accomplish this.

Matthew
  • 4,149
  • 2
  • 26
  • 53
2

encodeURIComponent is to pass variables over links using GET

JSON.stringify() encodes automatically into utf8

only in some rare cases for example when you want to convert strange charachters to base64 the encodeURIComponent is used outside from GET.

here is an example

base64_encode=function(a){
 return window.btoa(unescape(encodeURIComponent(a)));
};

https://developer.mozilla.org/en-US/docs/Web/API/window.btoa

said that ..

if you use a REST API service every ajax GET request which is a string parameter needs to be encoded with encodeURIComponent.

here is an example using yql

https://stackoverflow.com/a/18302867/2450730

Community
  • 1
  • 1
cocco
  • 16,442
  • 7
  • 62
  • 77
0

No they do not. There is no need for it when it is send as data through Ajax POST.

You can send pure JSON unencoded using AJAX

var ajaxObject = $.ajax({
    url: 'url',
    type: 'POST',
    data: JSON.stringify(object_literal);
}); 
Rene Pot
  • 24,681
  • 7
  • 68
  • 92
  • The `dataType` property is only used to indicate the type of data you expect in response from the server. It has nothing to do with indicating the content of the post itself. You should set the `contentType` property to `'application/json'`. – Brett Aug 22 '13 at 14:08
  • yeah, I probably shouldn't have included that part, but it was part of my code I use ;) – Rene Pot Aug 22 '13 at 14:26