Reputation: 12075
How can I retrieve the HTTP POST
request body when implementing NanoHTTPDs serve
method?
I've tried to use the getInputStream()
method of IHTTPSession
already, but I always get an SocketTimeoutException
when using it inside of the serve
method.
Upvotes: 24
Views: 22098
Reputation: 11
I've used this method and worked for me without socket exception.
String body = "";
try {
Map<String, String> headers = session.getHeaders();
if (headers == null || headers.get("content-length") == null) {
iDoMethodInThread.onException(new Exception("No Content length found in header"));
return;
}
int contentLength = Integer.parseInt(headers.get("content-length"));
byte[] buffer = new byte[contentLength];
int totalRead = 0;
while (totalRead < contentLength) {
int read = session.getInputStream().read(buffer, totalRead, contentLength - totalRead);
if (read == -1) {
break;
}
totalRead += read;
}
body = new String(buffer, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
Upvotes: 1
Reputation: 382
This is how I am getting my post response body with NanoHttp, and it works for me. Very important to note that if you are handling your own error response codes and want to send a body use the error input stream instead of the conn.getInputStream() This will avoid the file not found exception or broken pipe exception if close the connection before the server sent the body.
public HashMap<String, Object> getResponse(HttpURLConnection conn) throws IOException {
Log.i("STATUS", String.valueOf(conn.getResponseCode()));
Log.i("MSG", conn.getResponseMessage());
StringBuilder response = new StringBuilder();
String line;
BufferedReader br;
if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK)
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
else
br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
while ((line = br.readLine()) != null)
response.append(line);
conn.disconnect();
return new Gson().fromJson(response.toString(), HashMap.class);
Upvotes: 0
Reputation: 3061
I think session.getQueryParameterString();
not work in this case.
If you using POST
, PUT
, you should want to try this code:
Integer contentLength = Integer.parseInt(session.getHeaders().get("content-length"));
byte[] buffer = new byte[contentLength];
session.getInputStream().read(buffer, 0, contentLength);
Log.d("RequestBody: " + new String(buffer));
In fact, I tried IOUtils.toString(inputstream, encoding)
but it cause Timeout exception
!
Upvotes: 12
Reputation: 879
On a IHTTPSession
instance you can call the .parseBody(Map<String, String>)
method which will then fill the map you provided with some values.
Afterwards your map may contain a value under the key postBody
.
final HashMap<String, String> map = new HashMap<String, String>();
session.parseBody(map);
final String json = map.get("postData");
This value will then hold your posts body.
Code that does this, can be found here.
Upvotes: 32
Reputation: 4139
In the serve
method you first have to call session.parseBody(files)
, where files
is a Map<String, String>
, and then session.getQueryParameterString()
will return the POST
request's body.
I found an example in the source code. Here is the relevant code:
public Response serve(IHTTPSession session) {
Map<String, String> files = new HashMap<String, String>();
Method method = session.getMethod();
if (Method.PUT.equals(method) || Method.POST.equals(method)) {
try {
session.parseBody(files);
} catch (IOException ioe) {
return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
} catch (ResponseException re) {
return new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
}
}
// get the POST body
String postBody = session.getQueryParameterString();
// or you can access the POST request's parameters
String postParameter = session.getParms().get("parameter");
return new Response(postBody); // Or postParameter.
}
Upvotes: 33