I've got an iOS application, and we've been getting some errors that seem to be related to encoding problems because some of content is getting truncated when it reaches the server. This is problematic because it's been messing with our authentication mechanism, which involves making a hash of the posted content (along with some other stuff, but that's the basics).
So far we haven't been able to reproduce the problem locally. We have a theory that it's related to something like, an emoji keyboard; but I've tried posting emojis, international characters, everything that I could think of. Everything gets posted correctly when I try it. I know that there was a difference in the way ios encodes emoji between ios 4 and 5; we've managed to speak with a few of our customers to try to get an idea about what they're using, and it's usually iOS 6, with either an iphone 4s, or 5 (just like our test devices, I've tested with ios 5 and 6) ... so it wouldn't seem to be related to the OS.
This is how we are setting the request's body for the post.
[req setHTTPBody:[paramString dataUsingEncoding:NSUTF8StringEncoding]];
Previously, I was just setting the content-type to this:
[req setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
And my theory is that being explicit about the charset in the content type might fix it:
[req setValue:#"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
So my question for you SO, is this crazy? do you think being explicit in setting the charset to UTF-8 would resolve the issue? Any other troubleshooting techniques that you can recommend to figure out where the problem is occurring?
Do you have a wireshark or fiddler trace of a failing request? I would start there to verify that the client is indeed sending truncated data, and it's not a server side issue.
Check that the Content-Length header is correct regardless of data sent. Since the issue is not easily reproducible, perhaps collect more specific data from users who saw the problem, so the problematic inputs can be identified, and the broken request can be reproduced repeatedly.
I doubt it's an encoding issue if you are pulling strings straight from a UITextField, you shouldn't have encoding issues. If you are going to/from CStrings or NSData then that would be the first place to check.
Not a conclusive answer by any means, but that's where I would start.
Related
I have weird issue running the last version of Raknet on iOS with Unity3D: I get CONNECTION_ATTEMPT_FAILED when trying to connect to the server.
Now let's me detail the issue:
he exact same Library connects fine when used in an ObjectiveC application, so the issue seems to be Unity3D related.
I already managed to pinpoint my issue to be located in Raknet reliability layer:
Apparently, during the last step of the connection process (when the connection handshake as been completed) the reliability layer of the server thinks that the ID_CONNECTION_REQUEST packet received from the client is an acknowledgment instead of a message. Therefore it doesn't answer. Ultimately after a few tries, (and a 10s timeout) the client fails with the CONNECTION_ATTEMPT_FAILED error.
Does anybody there as an idea? I will update the question when I manage to get more info.
Update
We are using Unity3D 5.1.1f1
We managed to find a workaround! See answer for more information. As the workaround doesn't tell us much about what really happened, I would gladly hear some C++/XCode/Unity/iOS/AppleLLVM6.1 experts around here explain what really happened.
The issue was that the Raknet header wasn't properly generated by the iOS client. Namely we were sending ACK messages in place of simple packets. The rest of the message was considered as garbage by the server and the packet was dropped. The client kept trying to send the corrupted handshake packet a few times before timeouting.
This doesn't tell us why, doesn't it? Apparently the serialize method of the class DatagramHeaderFormat wasn't called as it should have been when running Raknet in Unity (iOS). Something else (and I don't know what) was linked in place of this method and was filling the BitStream with a corrupted header.
I am quite sure that the serialize method wasn't called because printf calls from inside weren't displayed in the console.
We renamed DatagramHeaderFormat::serialize into DatagramHeaderFormat::serializeHeader and... voila, it works.
Now I only want to understand what did the compiler (and why).
I'm watching the Stanford CS193p lecture video. The instructor used both downloadTaskWithRequest: and downloadTaskWithURL: when downloading some photos from Flickr. I'm a bit confused.
I looked up the former in the documentation, which speaks of the NSURLRequest as "An NSURLRequest object that provides the URL, cache policy, request type, body data or body stream, and so on".
I have no idea what "body data" or "body stream" means. It would be fantastic if anyone could help a bit on that, but more important is the problem below.
It seems to me that either method would work just fine according to my experience (which isn't much).
I'm intrigued to know what, if any, is the difference between the two, and on which occasions should I pick one over another.
If you use the NSURLRequest version, all the details you mentioned can be explicitly set by you. If you use the NSURL version then the default values will be used instead. The default values will cover the majority of cases, but not everything - it really depends on what you're doing.
The body data / body stream (where a stream is a source of data) is some piece of information that needs to be sent to the server for it to understand and process the request. By default no data will be sent. Often you will use query parameters in the URL instead of body data, but again, it depends what you're doing as to what API you need to leverage.
I am trying to adjust the timeout on a NSMutableURLRequest for a simple HTTP GET using setTimeoutSeconds:, but not having any luck. It seems to work for any values under 60.0, but if I set a larger value (ex: 90.0), then it still times out at one minute. I've tried setting it to 0.0 hoping it would have no timeout, but no luck there.
I have read many posts on this subject, some about POST issue which doesn't apply, but never seen a solid answer.
It seems to be a bug in iOS but I can't see anyway around it. I don't want to use ASIHTTPRequest, I need a workaround that I can use with NSMutableURLRequest.
Can anyone please help?
I have an app on the appStore that syncs xml data to a webservice. I've had two error reports today caused by the xml document ending prematurely. One ended right in the middle of an xml tag, so I know it isn't a problem caused by special characters. One of the errors occurred at 184kb, the other at 302kb, so it's not a problem with the request being truncated after so many bytes. It does seem to only be a problem on longer requests though.
Are there any specific settings that will prevent this truncation from happening?
I've been able to reproduce this by shutting down my app before the NSURLConnection finishes sending the request. I'm guessing the same thing was happening with a couple of my app users.
I read some of the similar posts on this site that deal with what seems to be the same issue and the responses didn't really seem to clarify things for me.
My application works fine in the simulator. I believe I'm on Bold 9000 with OS 4.6. The app is signed.
My app makes an HTTP call via 3G to fetch an XML result. type is application/xhtml+xml.
In the device, it gives no error. it makes no visual sign of error. I tell the try catch to print the results to the screen and I get nothing.
HttpConnection was taken right out of the demos and works fine in sim.
Since it gives no error, I begin to reflect back on things I recall reading back when the project began. deviceside=true? Something like that?
My request is simply HttpConnection connection = (HttpConnection)Connector.open(url);
where url is just a standard url, no get vars.
Based on the amount of time I see the connection arrows in the corner of the screen, I assume the app is launching the initial communication to my server, then either getting a bad result, or it gets results and the persistent store is not functioning as expected.
I have no idea where to begin with this. Posting code would be ridiculous since it would be basically my whole app.
I guess my question is if anyone knows of any major differences with device versus simulator that could cause something like http connection or persistent store to fail?
A build setting? An OS restriction? Any standard procedure I may have just not known about that everyone should do before beginning device testing?
Thanks
Just providing the URL will not work. You will have to append some info after the URL to determine the transport method your HTTP connection will use. For instance http://example.com;deviceside=true will use DirectTCP (you might also have to supply APN information but that's saved on the device for my phone). http://example.com;interface=wifi will use wi-fi. On OS 5 there's a ConnectionFactory class that makes this a lot easier. Here's a link that goes into more detail.
This was a tough one for me!
As Jonathan said you have to put some parameters in the url to make it work on the device. You shouldn't do it by hand but use the ConnectionFactory instead.
As you may thing this would just make it work but it doesn't!
The real problem is that not the url has been altered because it has ;interface=wifi;deviceside=true in it (in my case). Depending on the webserver accepting your request this could broke the code.
A solution I tried and that works is try to happend a fake parameter like
&foo=true -> &foo=true;deviceside=true
This will result as a standard parameter for the webserver but your device would use it to driver your connection.
On the simulator this work without this extra code because behind it there is a BIS server for you. On the device (as in my case) there isn't because I'm using a development device unregistered and without SIM (just wifi).
Another point is that the HttpConnection class doesn't handle HTTP 302 Redirect and if you get one you have to handle it manually.
It's probably an issue with the APN not being specified. See my answer for this question for details:
video streaming over http in blackberry
I would make this a comment, but I think I don't have enough rep yet for that... So I'll just answer and hope this doesn't get hosed for just pasting in some links.
I've been working on this exact sort of networking issue on our app this past week, and it is indeed tricky as some others have pointed out. Here are two links which really helped us out using HTTP on different devices, especially older devices which do not provide ConnectionFactory.
http://supportforums.blackberry.com/t5/Java-Development/Connecting-your-BlackBerry-http-and-socket-connections-to-the/td-p/206242
The first one has some code examples, including demonstration of querying the system's ServiceBook and CoverageInfo classes to make a decision about what kind of connection will work.