package com.koushikdutta.async.http; import com.koushikdutta.async.AsyncServer; import com.koushikdutta.async.DataEmitter; import com.koushikdutta.async.FilteredDataEmitter; import com.koushikdutta.async.callback.CompletedCallback; import com.koushikdutta.async.http.filter.ChunkedInputFilter; import com.koushikdutta.async.http.filter.ContentLengthFilter; import com.koushikdutta.async.http.filter.GZIPInputFilter; import com.koushikdutta.async.http.filter.InflaterInputFilter; import com.koushikdutta.async.http.libcore.RawHeaders; import com.koushikdutta.async.http.server.UnknownRequestBody; public class HttpUtil { public static AsyncHttpRequestBody getBody(DataEmitter emitter, CompletedCallback reporter, RawHeaders headers) { String contentType = headers.get("Content-Type"); if (contentType != null) { String[] values = contentType.split(";"); for (int i = 0; i < values.length; i++) { values[i] = values[i].trim(); } for (String ct: values) { if (UrlEncodedFormBody.CONTENT_TYPE.equals(ct)) { return new UrlEncodedFormBody(); } if (JSONObjectBody.CONTENT_TYPE.equals(ct)) { return new JSONObjectBody(); } if (StringBody.CONTENT_TYPE.equals(ct)) { return new StringBody(); } if (MultipartFormDataBody.CONTENT_TYPE.equals(ct)) { return new MultipartFormDataBody(contentType, values); } } } return new UnknownRequestBody(contentType); } private static class EndEmitter extends FilteredDataEmitter { private EndEmitter() { } public static EndEmitter create(AsyncServer server, final Exception e) { final EndEmitter ret = new EndEmitter(); // don't need to worry about any race conditions with post and this return value // since we are in the server thread. server.post(new Runnable() { @Override public void run() { ret.report(e); } }); return ret; } } public static DataEmitter getBodyDecoder(DataEmitter emitter, RawHeaders headers, boolean server) { int _contentLength; try { _contentLength = Integer.parseInt(headers.get("Content-Length")); } catch (Exception ex) { _contentLength = -1; } final int contentLength = _contentLength; if (-1 != contentLength) { if (contentLength < 0) { EndEmitter ender = EndEmitter.create(emitter.getServer(), new Exception("not using chunked encoding, and no content-length found.")); ender.setDataEmitter(emitter); emitter = ender; return emitter; } if (contentLength == 0) { EndEmitter ender = EndEmitter.create(emitter.getServer(), null); ender.setDataEmitter(emitter); emitter = ender; return emitter; } ContentLengthFilter contentLengthWatcher = new ContentLengthFilter(contentLength); contentLengthWatcher.setDataEmitter(emitter); emitter = contentLengthWatcher; } else if ("chunked".equalsIgnoreCase(headers.get("Transfer-Encoding"))) { ChunkedInputFilter chunker = new ChunkedInputFilter(); chunker.setDataEmitter(emitter); emitter = chunker; } else { if (server || headers.getStatusLine().contains("HTTP/1.1")) { // if this is the server, and the client has not indicated a request body, the client is done EndEmitter ender = EndEmitter.create(emitter.getServer(), null); ender.setDataEmitter(emitter); emitter = ender; return emitter; } } if ("gzip".equals(headers.get("Content-Encoding"))) { GZIPInputFilter gunzipper = new GZIPInputFilter(); gunzipper.setDataEmitter(emitter); emitter = gunzipper; } else if ("deflate".equals(headers.get("Content-Encoding"))) { InflaterInputFilter inflater = new InflaterInputFilter(); inflater.setDataEmitter(emitter); emitter = inflater; } // conversely, if this is the client (http 1.0), and the server has not indicated a request body, we do not report // the close/end event until the server actually closes the connection. return emitter; } }