{"action":"closed","issue":{"url":"https://api.github.com/repos/NanoHttpd/nanohttpd/issues/91","labels_url":"https://api.github.com/repos/NanoHttpd/nanohttpd/issues/91/labels{/name}","comments_url":"https://api.github.com/repos/NanoHttpd/nanohttpd/issues/91/comments","events_url":"https://api.github.com/repos/NanoHttpd/nanohttpd/issues/91/events","html_url":"https://github.com/NanoHttpd/nanohttpd/issues/91","id":24785945,"number":91,"title":"File Uploads Cause the App to crash with StackOverflowError","user":{"login":"lordspace","id":137558,"avatar_url":"https://avatars.githubusercontent.com/u/137558?v=3","gravatar_id":"","url":"https://api.github.com/users/lordspace","html_url":"https://github.com/lordspace","followers_url":"https://api.github.com/users/lordspace/followers","following_url":"https://api.github.com/users/lordspace/following{/other_user}","gists_url":"https://api.github.com/users/lordspace/gists{/gist_id}","starred_url":"https://api.github.com/users/lordspace/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lordspace/subscriptions","organizations_url":"https://api.github.com/users/lordspace/orgs","repos_url":"https://api.github.com/users/lordspace/repos","events_url":"https://api.github.com/users/lordspace/events{/privacy}","received_events_url":"https://api.github.com/users/lordspace/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/NanoHttpd/nanohttpd/labels/bug","name":"bug","color":"fc2929"}],"state":"closed","locked":false,"assignee":{"login":"elonen","id":2125766,"avatar_url":"https://avatars.githubusercontent.com/u/2125766?v=3","gravatar_id":"","url":"https://api.github.com/users/elonen","html_url":"https://github.com/elonen","followers_url":"https://api.github.com/users/elonen/followers","following_url":"https://api.github.com/users/elonen/following{/other_user}","gists_url":"https://api.github.com/users/elonen/gists{/gist_id}","starred_url":"https://api.github.com/users/elonen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elonen/subscriptions","organizations_url":"https://api.github.com/users/elonen/orgs","repos_url":"https://api.github.com/users/elonen/repos","events_url":"https://api.github.com/users/elonen/events{/privacy}","received_events_url":"https://api.github.com/users/elonen/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/NanoHttpd/nanohttpd/milestones/2","html_url":"https://github.com/NanoHttpd/nanohttpd/milestones/2.2.0","labels_url":"https://api.github.com/repos/NanoHttpd/nanohttpd/milestones/2/labels","id":1127282,"number":2,"title":"2.2.0","description":"next release planned for June 2015","creator":{"login":"ritchieGitHub","id":9456779,"avatar_url":"https://avatars.githubusercontent.com/u/9456779?v=3","gravatar_id":"","url":"https://api.github.com/users/ritchieGitHub","html_url":"https://github.com/ritchieGitHub","followers_url":"https://api.github.com/users/ritchieGitHub/followers","following_url":"https://api.github.com/users/ritchieGitHub/following{/other_user}","gists_url":"https://api.github.com/users/ritchieGitHub/gists{/gist_id}","starred_url":"https://api.github.com/users/ritchieGitHub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ritchieGitHub/subscriptions","organizations_url":"https://api.github.com/users/ritchieGitHub/orgs","repos_url":"https://api.github.com/users/ritchieGitHub/repos","events_url":"https://api.github.com/users/ritchieGitHub/events{/privacy}","received_events_url":"https://api.github.com/users/ritchieGitHub/received_events","type":"User","site_admin":false},"open_issues":6,"closed_issues":1,"state":"open","created_at":"2015-05-24T07:26:32Z","updated_at":"2015-05-24T07:56:04Z","due_on":null,"closed_at":null},"comments":6,"created_at":"2013-12-26T11:44:02Z","updated_at":"2015-05-24T07:56:04Z","closed_at":"2015-05-24T07:56:04Z","body":"First, off great job with the project.\r\nI think I found a glitch. When I try to upload a file the server crashes.\r\n\r\nI used the following form to submit an upload to my android web server\r\n`\r\n<html>\r\n<body>\r\n\r\n\t<form action=\"http://192.168.0.107:8181/\" method=\"post\" enctype=\"multipart/form-data\">\r\n\t\t<label for=\"file\">Filename:</label>\r\n\t\t<input type=\"file\" name=\"file\" id=\"file\"><br>\r\n\t\t<input type=\"submit\" name=\"submit\" value=\"Submit\">\r\n\t</form>\r\n\r\n</body>\r\n</html>\r\n\r\n`12-26 06:38:07.868: E/AndroidRuntime(7292): FATAL EXCEPTION: NanoHttpd Request Processor (#2)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): java.lang.StackOverflowError\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputStream.read(SequenceInputStream.java:201)\r\n12-26 06:38:07.868: E/AndroidRuntime(7292): \tat java.io.SequenceInputSt\r\n12-26 06:38:08.038: D/dalvikvm(7292): GC_FOR_MALLOC freed 393K, 39% free 4962K/8007K, external 0K/0K, paused 18ms\r\n12-26 06:38:08.358: D/WindowManagerImpl(7292): finishRemoveViewLocked, mViews[0]: com.android.internal.policy.impl.PhoneWindow$DecorView@405224f8\r\n`\r\n\r\nHere is how I am using the server\r\n`\r\npackage com.orbisius.serverapp;\r\n\r\nimport java.io.IOException;\r\nimport java.net.InetAddress;\r\nimport java.net.NetworkInterface;\r\nimport java.net.SocketException;\r\nimport java.util.Enumeration;\r\nimport java.util.HashMap;\r\nimport java.util.List;\r\nimport java.util.Map;\r\nimport java.util.Map.Entry;\r\nimport java.util.Properties;\r\n\r\nimport android.net.wifi.WifiManager;\r\nimport android.os.Bundle;\r\nimport android.os.Handler;\r\nimport android.app.Activity;\r\nimport android.util.Log;\r\nimport android.view.Menu;\r\nimport android.widget.TextView;\r\n\r\npublic class MainActivity extends Activity {\r\n\r\n\tprivate static final int PORT = 8181;\r\n\tprivate TextView hello;\r\n\tprivate MyHTTPD server;\r\n\tprivate Handler handler = new Handler();\r\n\r\n\t@Override\r\n\tprotected void onCreate(Bundle savedInstanceState) {\r\n\t\tsuper.onCreate(savedInstanceState);\r\n\t\tsetContentView(R.layout.activity_main);\r\n\r\n\t\thello = (TextView) findViewById(R.id.hello);\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\r\n\t\t// Inflate the menu; this adds items to the action bar if it is present.\r\n\t\tgetMenuInflater().inflate(R.menu.main, menu);\r\n\t\treturn true;\r\n\t}\r\n\r\n\t@Override\r\n\tprotected void onResume() {\r\n\t\tsuper.onResume();\r\n\r\n\t\tTextView textIpaddr = (TextView) findViewById(R.id.ipaddr);\r\n\t\tWifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);\r\n\t\tint ipAddress = wifiManager.getConnectionInfo().getIpAddress();\r\n\t\tfinal String formatedIpAddress = String.format(\"%d.%d.%d.%d\",\r\n\t\t\t\t(ipAddress & 0xff), (ipAddress >> 8 & 0xff),\r\n\t\t\t\t(ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));\r\n\t\ttextIpaddr.setText(\"Please access! http://\" + formatedIpAddress \r\n\t\t\t\t+ \":\" + PORT + \" or \" + getLocalIpAddress() + \":\" + PORT );\r\n\r\n\t\ttry {\r\n\t\t\tserver = new MyHTTPD();\r\n\t\t\tserver.start();\r\n\t\t} catch (IOException e) {\r\n\t\t\te.printStackTrace();\r\n\t\t}\r\n\t}\r\n\r\n\t@Override\r\n\tprotected void onPause() {\r\n\t\tsuper.onPause();\r\n\t\tif (server != null)\r\n\t\t\tserver.stop();\r\n\t}\r\n\r\n\tpublic String getLocalIpAddress() {\r\n\t\ttry {\r\n\t\t\tfor (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {\r\n\t\t\t\tNetworkInterface intf = en.nextElement();\r\n\t\t\t\t\r\n\t\t\t\tfor (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr\r\n\t\t\t\t\t\t.hasMoreElements();) {\r\n\t\t\t\t\tInetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (!inetAddress.isLoopbackAddress()) {\r\n\t\t\t\t\t\treturn inetAddress.getHostAddress().toString();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} catch (SocketException ex) {\r\n\t\t\tLog.e(\"Exception\", ex.toString());\r\n\t\t}\r\n\t\t\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// https://github.com/NanoHttpd/nanohttpd\r\n\tprivate class MyHTTPD extends NanoHTTPD {\r\n\t\tpublic MyHTTPD() throws IOException {\r\n\t\t\tsuper(PORT);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Response serve(IHTTPSession session) {\r\n\t\t\tMap<String, List<String>> decodedQueryParameters = decodeParameters(session\r\n\t\t\t\t\t.getQueryParameterString());\r\n\r\n\t\t\tStringBuilder sb = new StringBuilder();\r\n\t\t\tsb.append(\"<html>\");\r\n\t\t\tsb.append(\"<head><title>Debug Server</title></head>\");\r\n\t\t\tsb.append(\"<body>\");\r\n\t\t\tsb.append(\"<h1>Debug Server</h1>\");\r\n\r\n\t\t\tsb.append(\"<p><blockquote><b>URI</b> = \")\r\n\t\t\t\t\t.append(String.valueOf(session.getUri())).append(\"<br />\");\r\n\r\n\t\t\tsb.append(\"<b>Method</b> = \")\r\n\t\t\t\t\t.append(String.valueOf(session.getMethod()))\r\n\t\t\t\t\t.append(\"</blockquote></p>\");\r\n\r\n\t\t\tsb.append(\"<h3>Headers</h3><p><blockquote>\")\r\n\t\t\t\t\t.append(toString(session.getHeaders()))\r\n\t\t\t\t\t.append(\"</blockquote></p>\");\r\n\r\n\t\t\tsb.append(\"<h3>Parms</h3><p><blockquote>\")\r\n\t\t\t\t\t.append(toString(session.getParms()))\r\n\t\t\t\t\t.append(\"</blockquote></p>\");\r\n\r\n\t\t\tsb.append(\"<h3>Parms (multi values?)</h3><p><blockquote>\")\r\n\t\t\t\t\t.append(toString(decodedQueryParameters))\r\n\t\t\t\t\t.append(\"</blockquote></p>\");\r\n\r\n\t\t\ttry {\r\n\t\t\t\tMap<String, String> files = new HashMap<String, String>();\r\n\t\t\t\tsession.parseBody(files);\r\n\t\t\t\tsb.append(\"<h3>Files</h3><p><blockquote>\")\r\n\t\t\t\t\t\t.append(toString(files)).append(\"</blockquote></p>\");\r\n\t\t\t} catch (Exception e) {\r\n\t\t\t\te.printStackTrace();\r\n\t\t\t}\r\n\r\n\t\t\tsb.append(\"</body>\");\r\n\t\t\tsb.append(\"</html>\");\r\n\t\t\treturn new Response(sb.toString());\r\n\t\t}\r\n\r\n\t\tprivate String toString(Map<String, ? extends Object> map) {\r\n\t\t\tif (map.size() == 0) {\r\n\t\t\t\treturn \"\";\r\n\t\t\t}\r\n\t\t\treturn unsortedList(map);\r\n\t\t}\r\n\r\n\t\tprivate String unsortedList(Map<String, ? extends Object> map) {\r\n\t\t\tStringBuilder sb = new StringBuilder();\r\n\t\t\tsb.append(\"<ul>\");\r\n\t\t\tfor (Map.Entry entry : map.entrySet()) {\r\n\t\t\t\tlistItem(sb, entry);\r\n\t\t\t}\r\n\t\t\tsb.append(\"</ul>\");\r\n\t\t\treturn sb.toString();\r\n\t\t}\r\n\r\n\t\tprivate void listItem(StringBuilder sb, Map.Entry entry) {\r\n\t\t\tsb.append(\"<li><code><b>\").append(entry.getKey()).append(\"</b> = \")\r\n\t\t\t\t\t.append(entry.getValue()).append(\"</code></li>\");\r\n\t\t}\r\n\t}\r\n}\r\n`"}}