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

Using Http connection from iOS client gives error on server #106

Closed
codenameone opened this issue Mar 27, 2015 · 5 comments
Closed

Using Http connection from iOS client gives error on server #106

codenameone opened this issue Mar 27, 2015 · 5 comments

Comments

@codenameone
Copy link
Collaborator

Original issue 106 created by codenameone on 2012-03-16T13:38:12.000Z:

What steps will reproduce the problem?

  1. Create a ConnectionRequest class with code similar to the following code:

ConnectionRequest actReq = new ConnectionRequest() {
protected void buildRequestBody(OutputStream os) throws IOException {
super.buildRequestBody(os);
// Write the JSON object as UTF string
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(requestObj.toString());
// Adding or removing the flush stmt does not make any difference in the error
//dos.flush();
}
};
// Allow duplicate network connection request, as we will always
// send the request to the same URL however with different form data
actReq.setDuplicateSupported(true);
actReq.setUrl("http://som-server-url");
actReq.setSilentRetryCount(1); // Silently retry one more time before giving error
actReq.setPost(true);
actReq.setContentType("application/json");
actReq.addRequestHeader("Accept", "application/json");
actReq.addRequestHeader("CLIENT_API_VERSION","1.0");

        NetworkManager.getInstance().addToQueue(actReq);
  1. On the server side, you will need a servlet which can read the post request sent by above client code:

Inside the servlet, code the following to read the response(where req is of type HttpServletRequest ):

try {
DataInputStream in = new DataInputStream(req.getInputStream());
HttpSession session = req.getSession(true);
String versionString = req.getHeader("CLIENT_API_VERSION");
String inStr = in.readUTF();
} catch (Exception e) {
e.printStackTrace();
}

3.

What is the expected output? What do you see instead?

In the simulator environment, the above code works fine and server is able to get the response. However when using the code in actual device iPhone (iOS), the connection request is received at the server, but it fails with the following error:

java.io.EOFException

at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:323)

at java.io.DataInputStream.readUTF(DataInputStream.java:572)

at java.io.DataInputStream.readUTF(DataInputStream.java:547)

Also the versionString(CLIENT_API_VERSION) request header is coming out to be null when request is from actual device.

What version of the product are you using? On what operating system?

the public beta code released on March 15, 2012. On Mac OS and iPhone 4 (OS ver 5.1)

Please provide any additional information below.

@codenameone
Copy link
Collaborator Author

Comment #1 originally posted by codenameone on 2012-03-17T12:45:03.000Z:

I reviewed the code you sent through the group and fixed a bug in our code where you didn't get a response so I'm closing this issue as fixed.
Your code still doesn't work correctly on the device due to several issues specific to your code. First:
new Thread() {
public void run() {
activateDevice(url);
}

        }.start();

The method activateDevice shows a GUI, which is illegal on a separate thread (this causes problems). You don't need to worry about the networking code since its all asynchronous!

Second:
super.buildRequestBody(os);
// Write the JSON object as UTF string
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("{"ID":"101"}");

And this:
ByteArrayInputStream byteInStram = null;
DataInputStream inStream = null;
try {
byteInStram = new ByteArrayInputStream((byte[]) netEvt.getMetaData());
inStream = new DataInputStream(byteInStram);
String inStr = inStream.readUTF();
showAlert("Response",
"Received JSON response string[" + inStr + "]");
} catch (IOException e) {
showAlert("Error",
"IO Error reading the response JSON object" + e);
} finally {
Util.cleanup(inStream);
Util.cleanup(byteInStram);
}

Produce a string that isn't quite UTF 8 and includes a BOM. The problem is it seems the server side code also returns a value such as this and the IOS side of things bulks at translating the binary data correctly.
So you effectively get an empty string.

Use methods such as:
protected void buildRequestBody(OutputStream os) throws IOException {
// Write the JSON object as UTF string
os.write("{"ID":"101"}".getBytes("UTF-8"));
}

And this:
public void actionPerformed(ActionEvent ae) {
NetworkEvent netEvt = (NetworkEvent) ae;
try {
byte[] data = (byte[]) netEvt.getMetaData();
String inStr = new String(data, "UTF-8");
showAlert("Response",
"Received JSON response string[" + inStr + "]");
} catch (Throwable e) {
showAlert("Error",
"Error reading the response JSON object" + e);
}
}

Although with the data the server side sends you (it starts with a 0 20 bom) this won't work. You might need to trim the beginning of the data or change the server code.
You can open a separate issue about parsing a String in iOS which is an XMLVM bug. Unfortunately I don't know how easy it will be to get a fix from the XMLVM guys since their current SVN doesn't work for us at all. We intend to fix this in the long run either by fixing or replacing XMLVM with preference to the latter in order to reduce build times with a simpler architecture.

@codenameone
Copy link
Collaborator Author

Comment #2 originally posted by codenameone on 2012-03-17T15:00:54.000Z:

Hi Shai,

thanks for your help in resolving this.

The DataOutputStream.writeUTF() method writes the String in modified
UTF encoding and as per that it puts the number of bytes before actual
string. However, I have made the changes suggested by you on the
server and client, so that it is using the getBytes("UTF-8") to write
the request body.

Now the response is coming back from server. However the request is
not going to the server. On the server side, the request header is
coming as null and the request body is also coming as empty.

I believe the iOS port is probably still not writing the header or the
request body.

The new server URL is http://m.s2pay.com:8888/skey/jsonservice

On this server it is reading response from the input string as
directly UTF bytes.

Can you please take a look?

@codenameone
Copy link
Collaborator Author

Comment #3 originally posted by codenameone on 2012-03-17T18:53:49.000Z:

I've just added another fix to the server. It seems HTTP headers were sent in reverse (had the key/value the other way around). After making that change I get the exact same error on the iOS device as I get in the Codename One simulator.

@codenameone
Copy link
Collaborator Author

Comment #4 originally posted by codenameone on 2012-03-17T19:07:44.000Z:

In that case the fix should be working. Let me try re-building the app
and try again.

@codenameone
Copy link
Collaborator Author

Comment #5 originally posted by codenameone on 2012-03-17T19:35:36.000Z:

Hi,

Thank you, the http connection on iOS is now working fine.

Thanks for all the help.

@codenameone codenameone removed their assignment Jul 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

0 participants