REST API v1.1: Can not publish messages including single quotes or parentheses


#1

Setup: iOS application, using MGTwitterEngine, connecting to REST API v1.1 statuses/update.json endpoints.

When trying to publish a message that contains single quotes or parenthesis, the server fails to accept the request. The same message is uploaded without hassle using REST API v1.0.

This is the request (body contents in Spanish, sorry):
<OAMutableURLRequest https://api.twitter.com/1.1/statuses/update.json>, method = POST, headers = {
Authorization = “OAuth realm=”", oauth_consumer_key=“xQ2ZbuS7u0Vh8DHmBnxrw”, oauth_token=“239470531-h2P91G6ey9yxkf3jhnsjWkBsVXsWuQMdRRQlmBWm”, oauth_signature_method=“HMAC-SHA1”, oauth_signature=“RtsgsOFxYBENlMyNnDsTCB0eS%2F0%3D”, oauth_timestamp=“1353687958”, oauth_nonce=“5FBF39FB-F8C6-47EE-B903-7CB2A9BDD1B3”, oauth_version=“1.0”, oauth_verifier=“zW4bwfVZrot6FnXaKge6tFMu7Y1VnMUNlZ1P373o4"”;
[some x-twitter-headers omitted on purpose]
}, body = status=Tiene%20(Viernes%20Negro)%20inicio%20anticipado%0Ahttp%3A%2F%2Fwww.elnorte.com%2Finternacional%2Farticulo%2F718%2F1434974%2F%3Fcompartir%3D5dbec681526f1c15b436be512d3cf5ba&source=gruporeforma

Delegate didReceiveResponse comes with error:
Error Domain=HTTP Code=401 “The operation couldn’t be completed. (HTTP error 401.)”

I appreciate any insights on what I’m doing wrong.


#2

API v1.1 (and in general all of our APIs) are getting stricter with OAuth and HTTP. In the HTTP spec, some characters are required to be encoded in URLs and POST bodies, including parens and single quotes.


#3

Thanks Taylor, that helped. Encoding these characters: !*’();:@&=+$,/?%#[]{}<> gets the request through. I wonder if I’m covering all special characters required by the HTTP Spec?


#4

Just for record, I found the IETF Standard that lists the reserved characters, http://tools.ietf.org/html/rfc3986#section-2.2. General information about percent encoding can be found at http://en.wikipedia.org/wiki/Percent-encoding.


#5

even for normal text post also I’m getting same 401 error. URL:https://api.twitter.com/1.1/statuses/update.json
method: POST
headers Is:
OAuth oauth_consumer_key=“vLsFeiLzHBFzkkkWxBHdpw”,oauth_nonce=“FazuSNqmzPRzHpSSqkrK”,oauth_signature_method=“HMAC-SHA1”,oauth_timestamp=“1354006156”,oauth_token=“177855597-sgYWNghonTFw0VBMIxWC1eMkEdeHZnmotkhHyQOC”,oauth_version=“1.0”,oauth_signature=“ANu%2B6AzGxUaV14aR2LAfhjoV6cY%3D”

Request Body Is: status=Great


#6

Besides the character encoding mentioned in this thread, there are other issues that may cause the same error, including: limit rating, clock synchronization between your device and Twitter (your timestamp looks fine, though), even the OAuth signing process.

Try pointing to REST API 1.0 or even changing the format to XML, to see what you get.


#7

pointing to REST API 1.0 is working fine. I’m getting problem only with v1.1 API


#8

Glad I’m not the only one running into this problem. API v1 works fine, API v1.1 returns 401 when I try to post special characters like !()’* , all the ones not automatically escaped via javascript’s encodeURIComponent() method. I’ve tried so many workarounds.

reverting to v1 worked for me.


#9

Javascript’s encodeURIComponent method is not adequate for encoding URLs, despite the name. This article has more details on how to adapt that Javascript function to a more technically correct one: http://af-design.com/blog/2008/03/14/rfc-3986-compliant-uri-encoding-in-javascript/


#10

Some one please help !!! In v1 APIs its working fine, but on v1.1 API I’m getting 401 error…Please help…
I’m getting same 401 error. URL:https://api.twitter.com/1.1/statuses/update.json
method: POST
headers Is:
OAuth oauth_consumer_key=“vLsFeiLzHBFzkkkWxBHdpw”,oauth_nonce=“FazuSNqmzPRzHpSSqkrK”,oauth_signature_method=“HMAC-SHA1”,oauth_timestamp=“1354006156”,oauth_token=“177855597-sgYWNghonTFw0VBMIxWC1eMkEdeHZnmotkhHyQOC”,oauth_version=“1.0”,oauth_signature=“ANu%2B6AzGxUaV14aR2LAfhjoV6cY%3D”

Request Body Is: status=Great


#11

Based on episod’s answer I was able to modify the regular expressions to get this working.

toRFC3986 = function(string) {
	var tmp = encodeURIComponent(string);
	tmp = tmp.replace( /!/g,'%21' );
	tmp = tmp.replace( /\*/g,'%2A' );
	tmp = tmp.replace( /\(/g,'%28' );
	tmp = tmp.replace( /\)/g,'%29' );
	tmp = tmp.replace( /'/g,'%27' );
	return tmp 
}

Then I replaced all instances of encodeURIComponent with toRFC3986 and seems to work fine now.