@Override protected void sendContent(HttpExchange exchange, HttpContent content, Callback callback) { try { HttpClient client = getHttpChannel().getHttpDestination().getHttpClient(); ByteBufferPool bufferPool = client.getByteBufferPool(); ByteBuffer chunk = null; while (true) { ByteBuffer contentBuffer = content.getByteBuffer(); boolean lastContent = content.isLast(); HttpGenerator.Result result = generator.generateRequest(null, null, chunk, contentBuffer, lastContent); switch (result) { case NEED_CHUNK: { chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false); break; } case FLUSH: { EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint(); if (chunk != null) endPoint.write( new ByteBufferRecyclerCallback(callback, bufferPool, chunk), chunk, contentBuffer); else endPoint.write(callback, contentBuffer); return; } case SHUTDOWN_OUT: { shutdownOutput(); break; } case CONTINUE: { break; } case DONE: { assert generator.isEnd(); callback.succeeded(); return; } default: { throw new IllegalStateException(); } } } } catch (Exception x) { LOG.debug(x); callback.failed(x); } }
@Test public void testCachedPut() throws Exception { HttpFields header = new HttpFields(); header.put("Connection", "Keep-Alive"); header.put("tRansfer-EncOding", "CHUNKED"); header.put("CONTENT-ENCODING", "gZIP"); ByteBuffer buffer = BufferUtil.allocate(1024); BufferUtil.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtil.flipToFlush(buffer, 0); String out = BufferUtil.toString(buffer).toLowerCase(); Assert.assertThat( out, Matchers.containsString( (HttpHeader.CONNECTION + ": " + HttpHeaderValue.KEEP_ALIVE).toLowerCase())); Assert.assertThat( out, Matchers.containsString( (HttpHeader.TRANSFER_ENCODING + ": " + HttpHeaderValue.CHUNKED).toLowerCase())); Assert.assertThat( out, Matchers.containsString( (HttpHeader.CONTENT_ENCODING + ": " + HttpHeaderValue.GZIP).toLowerCase())); }
@Override protected RequestState dispose() { generator.abort(); RequestState result = super.dispose(); shutdownOutput(); return result; }
/* ------------------------------------------------------------ */ @Override protected void doStart() throws Exception { if (getStopAtShutdown()) ShutdownThread.register(this); LOG.info("jetty-" + __version); HttpGenerator.setServerVersion(__version); MultiException mex = new MultiException(); if (_threadPool == null) setThreadPool(new QueuedThreadPool()); try { super.doStart(); } catch (Throwable e) { mex.add(e); } if (_connectors != null) { for (int i = 0; i < _connectors.length; i++) { try { _connectors[i].start(); } catch (Throwable e) { mex.add(e); } } } if (isDumpAfterStart()) dumpStdErr(); mex.ifExceptionThrow(); }
@Test public void testCRLF() throws Exception { HttpFields header = new HttpFields(); header.put("name0", "value\r\n0"); header.put("name\r\n1", "value1"); header.put("name:2", "value:\r\n2"); ByteBuffer buffer = BufferUtil.allocate(1024); BufferUtil.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtil.flipToFlush(buffer, 0); String out = BufferUtil.toString(buffer); assertThat(out, containsString("name0: value??0")); assertThat(out, containsString("name??1: value1")); assertThat(out, containsString("name?2: value:??2")); }
/** * Get the inputStream from the connection. * * <p>If the associated response has the Expect header set to 100 Continue, then accessing the * input stream indicates that the handler/servlet is ready for the request body and thus a 100 * Continue response is sent. * * @return The input stream for this connection. The stream will be created if it does not already * exist. */ public ServletInputStream getInputStream() throws IOException { // If the client is expecting 100 CONTINUE, then send it now. if (_expect100Continue) { // is content missing? if (((HttpParser) _parser).getHeaderBuffer() == null || ((HttpParser) _parser).getHeaderBuffer().length() < 2) { if (_generator.isCommitted()) throw new IllegalStateException("Committed before 100 Continues"); ((HttpGenerator) _generator).send1xx(HttpStatus.CONTINUE_100); } _expect100Continue = false; } if (_in == null) _in = new HttpInput(HttpConnection.this); return _in; }
@Test public void testPutTo() throws Exception { HttpFields header = new HttpFields(); header.put("name0", "value0"); header.put("name1", "value:A"); header.add("name1", "value:B"); header.add("name2", ""); ByteBuffer buffer = BufferUtil.allocate(1024); BufferUtil.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtil.flipToFlush(buffer, 0); String result = BufferUtil.toString(buffer); assertThat(result, Matchers.containsString("name0: value0")); assertThat(result, Matchers.containsString("name1: value:A")); assertThat(result, Matchers.containsString("name1: value:B")); }
@Override protected void sendHeaders(HttpExchange exchange, HttpContent content, Callback callback) { Request request = exchange.getRequest(); ContentProvider requestContent = request.getContent(); long contentLength = requestContent == null ? -1 : requestContent.getLength(); String path = request.getPath(); String query = request.getQuery(); if (query != null) path += "?" + query; HttpGenerator.RequestInfo requestInfo = new HttpGenerator.RequestInfo( request.getVersion(), request.getHeaders(), contentLength, request.getMethod(), path); try { HttpClient client = getHttpChannel().getHttpDestination().getHttpClient(); ByteBufferPool bufferPool = client.getByteBufferPool(); ByteBuffer header = bufferPool.acquire(client.getRequestBufferSize(), false); ByteBuffer chunk = null; ByteBuffer contentBuffer = null; boolean lastContent = false; if (!expects100Continue(request)) { content.advance(); contentBuffer = content.getByteBuffer(); lastContent = content.isLast(); } while (true) { HttpGenerator.Result result = generator.generateRequest(requestInfo, header, chunk, contentBuffer, lastContent); switch (result) { case NEED_CHUNK: { chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false); break; } case FLUSH: { int size = 1; boolean hasChunk = chunk != null; if (hasChunk) ++size; boolean hasContent = contentBuffer != null; if (hasContent) ++size; ByteBuffer[] toWrite = new ByteBuffer[size]; ByteBuffer[] toRecycle = new ByteBuffer[hasChunk ? 2 : 1]; toWrite[0] = header; toRecycle[0] = header; if (hasChunk) { toWrite[1] = chunk; toRecycle[1] = chunk; } if (hasContent) toWrite[toWrite.length - 1] = contentBuffer; EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint(); endPoint.write( new ByteBufferRecyclerCallback(callback, bufferPool, toRecycle), toWrite); return; } default: { throw new IllegalStateException(); } } } } catch (Exception x) { LOG.debug(x); callback.failed(x); } }
@Override protected void reset() { generator.reset(); super.reset(); }
@Test public void testPOSTRequestNoContent() throws Exception { ByteBuffer header = BufferUtil.allocate(2048); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateRequest(null, null, null, null, true); Assert.assertEquals(HttpGenerator.Result.NEED_INFO, result); Assert.assertEquals(HttpGenerator.State.START, gen.getState()); Info info = new Info("POST", "/index.html"); info.getFields().add("Host", "something"); info.getFields().add("User-Agent", "test"); Assert.assertTrue(!gen.isChunking()); result = gen.generateRequest(info, null, null, null, true); Assert.assertEquals(HttpGenerator.Result.NEED_HEADER, result); Assert.assertEquals(HttpGenerator.State.START, gen.getState()); result = gen.generateRequest(info, header, null, null, true); Assert.assertEquals(HttpGenerator.Result.FLUSH, result); Assert.assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); Assert.assertTrue(!gen.isChunking()); String out = BufferUtil.toString(header); BufferUtil.clear(header); result = gen.generateResponse(null, null, null, null, false); Assert.assertEquals(HttpGenerator.Result.DONE, result); Assert.assertEquals(HttpGenerator.State.END, gen.getState()); Assert.assertTrue(!gen.isChunking()); Assert.assertEquals(0, gen.getContentPrepared()); Assert.assertThat(out, Matchers.containsString("POST /index.html HTTP/1.1")); Assert.assertThat(out, Matchers.containsString("Content-Length: 0")); }
@Test public void testRequestWithKnownContent() throws Exception { String out; ByteBuffer header = BufferUtil.allocate(4096); ByteBuffer chunk = BufferUtil.allocate(HttpGenerator.CHUNK_SIZE); ByteBuffer content0 = BufferUtil.toBuffer("Hello World. "); ByteBuffer content1 = BufferUtil.toBuffer("The quick brown fox jumped over the lazy dog."); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateRequest(null, null, null, content0, false); Assert.assertEquals(HttpGenerator.Result.NEED_INFO, result); Assert.assertEquals(HttpGenerator.State.START, gen.getState()); Info info = new Info("POST", "/index.html", 58); info.getFields().add("Host", "something"); info.getFields().add("User-Agent", "test"); result = gen.generateRequest(info, null, null, content0, false); Assert.assertEquals(HttpGenerator.Result.NEED_HEADER, result); Assert.assertEquals(HttpGenerator.State.START, gen.getState()); result = gen.generateRequest(info, header, null, content0, false); Assert.assertEquals(HttpGenerator.Result.FLUSH, result); Assert.assertEquals(HttpGenerator.State.COMMITTED, gen.getState()); Assert.assertTrue(!gen.isChunking()); out = BufferUtil.toString(header); BufferUtil.clear(header); out += BufferUtil.toString(content0); BufferUtil.clear(content0); result = gen.generateRequest(null, null, null, content1, false); Assert.assertEquals(HttpGenerator.Result.FLUSH, result); Assert.assertEquals(HttpGenerator.State.COMMITTED, gen.getState()); Assert.assertTrue(!gen.isChunking()); out += BufferUtil.toString(content1); BufferUtil.clear(content1); result = gen.generateResponse(null, null, null, null, true); Assert.assertEquals(HttpGenerator.Result.CONTINUE, result); Assert.assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); Assert.assertTrue(!gen.isChunking()); result = gen.generateResponse(null, null, null, null, true); Assert.assertEquals(HttpGenerator.Result.DONE, result); Assert.assertEquals(HttpGenerator.State.END, gen.getState()); out += BufferUtil.toString(chunk); BufferUtil.clear(chunk); Assert.assertThat(out, Matchers.containsString("POST /index.html HTTP/1.1")); Assert.assertThat(out, Matchers.containsString("Host: something")); Assert.assertThat(out, Matchers.containsString("Content-Length: 58")); Assert.assertThat( out, Matchers.containsString( "\r\n\r\nHello World. The quick brown fox jumped over the lazy dog.")); Assert.assertEquals(58, gen.getContentPrepared()); }