395220 New InputStream extension to allow a mix of EOL styles between headers and content
This commit is contained in:
parent
11cbe274af
commit
249068551f
|
@ -0,0 +1,106 @@
|
|||
package org.eclipse.jetty.util;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
|
||||
public class ReadLineInputStream extends BufferedInputStream
|
||||
{
|
||||
boolean _seenCRLF;
|
||||
boolean _skipLF;
|
||||
|
||||
public ReadLineInputStream(InputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
public ReadLineInputStream(InputStream in, int size)
|
||||
{
|
||||
super(in,size);
|
||||
}
|
||||
|
||||
public String readLine() throws IOException
|
||||
{
|
||||
mark(buf.length);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int b=super.read();
|
||||
if (b==-1)
|
||||
{
|
||||
markpos=-1;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (b=='\r')
|
||||
{
|
||||
int p=pos;
|
||||
|
||||
// if we have seen CRLF before, hungrily consume LF
|
||||
if (_seenCRLF && pos<count)
|
||||
{
|
||||
if (buf[pos]=='\n')
|
||||
pos+=1;
|
||||
}
|
||||
else
|
||||
_skipLF=true;
|
||||
int m=markpos;
|
||||
markpos=-1;
|
||||
return new String(buf,m,p-m-1,StringUtil.__UTF8_CHARSET);
|
||||
}
|
||||
|
||||
if (b=='\n')
|
||||
{
|
||||
if (_skipLF)
|
||||
{
|
||||
_skipLF=false;
|
||||
_seenCRLF=true;
|
||||
markpos++;
|
||||
continue;
|
||||
}
|
||||
int m=markpos;
|
||||
markpos=-1;
|
||||
return new String(buf,m,pos-m-1,StringUtil.__UTF8_CHARSET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read() throws IOException
|
||||
{
|
||||
int b = super.read();
|
||||
if (_skipLF)
|
||||
{
|
||||
_skipLF=false;
|
||||
if (_seenCRLF && b=='\n')
|
||||
b=super.read();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read(byte[] buf, int off, int len) throws IOException
|
||||
{
|
||||
if (_skipLF && len>0)
|
||||
{
|
||||
_skipLF=false;
|
||||
if (_seenCRLF)
|
||||
{
|
||||
int b = super.read();
|
||||
if (b==-1)
|
||||
return -1;
|
||||
|
||||
if (b!='\n')
|
||||
{
|
||||
buf[off]=(byte)(0xff&b);
|
||||
return 1+super.read(buf,off+1,len-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.read(buf,off,len);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -475,6 +475,7 @@ public class TypeUtil
|
|||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Deprecated
|
||||
public static byte[] readLine(InputStream in) throws IOException
|
||||
{
|
||||
byte[] buf = new byte[256];
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ReadLineInputStreamTest
|
||||
{
|
||||
BlockingArrayQueue<String> _queue = new BlockingArrayQueue<>();
|
||||
PipedInputStream _pin;
|
||||
volatile PipedOutputStream _pout;
|
||||
ReadLineInputStream _in;
|
||||
volatile Thread _writer;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
_queue.clear();
|
||||
_pin=new PipedInputStream();
|
||||
_pout=new PipedOutputStream(_pin);
|
||||
_in=new ReadLineInputStream(_pin);
|
||||
_writer=new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
OutputStream out=_pout;
|
||||
while (out!=null)
|
||||
{
|
||||
String s = _queue.poll(100,TimeUnit.MILLISECONDS);
|
||||
if (s!=null)
|
||||
{
|
||||
if ("__CLOSE__".equals(s))
|
||||
_pout.close();
|
||||
else
|
||||
{
|
||||
_pout.write(s.getBytes(StringUtil.__UTF8_CHARSET));
|
||||
Thread.sleep(50);
|
||||
}
|
||||
}
|
||||
out=_pout;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_writer=null;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
_writer.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception
|
||||
{
|
||||
_pout=null;
|
||||
while (_writer!=null)
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCR() throws Exception
|
||||
{
|
||||
_queue.add("\rHello\rWorld\r\r");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLF() throws Exception
|
||||
{
|
||||
_queue.add("\nHello\nWorld\n\n");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCRLF() throws Exception
|
||||
{
|
||||
_queue.add("\r\nHello\r\nWorld\r\n\r\n");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCRBlocking() throws Exception
|
||||
{
|
||||
_queue.add("");
|
||||
_queue.add("\r");
|
||||
_queue.add("Hello");
|
||||
_queue.add("\rWorld\r");
|
||||
_queue.add("\r");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLFBlocking() throws Exception
|
||||
{
|
||||
_queue.add("");
|
||||
_queue.add("\n");
|
||||
_queue.add("Hello");
|
||||
_queue.add("\nWorld\n");
|
||||
_queue.add("\n");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCRLFBlocking() throws Exception
|
||||
{
|
||||
_queue.add("\r");
|
||||
_queue.add("\nHello");
|
||||
_queue.add("\r\nWorld\r");
|
||||
_queue.add("\n\r");
|
||||
_queue.add("\n");
|
||||
_queue.add("");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals("Hello",_in.readLine());
|
||||
Assert.assertEquals("World",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHeaderLFBodyLF() throws Exception
|
||||
{
|
||||
_queue.add("Header\n");
|
||||
_queue.add("\n");
|
||||
_queue.add("\nBody\n");
|
||||
_queue.add("\n");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("Header",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
|
||||
byte[] body = new byte[6];
|
||||
_in.read(body);
|
||||
Assert.assertEquals("\nBody\n",new String(body,0,6,StringUtil.__UTF8));
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaderCRBodyLF() throws Exception
|
||||
{
|
||||
_queue.add("Header\r");
|
||||
_queue.add("\r");
|
||||
_queue.add("\nBody\n");
|
||||
_queue.add("\r");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("Header",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
|
||||
byte[] body = new byte[6];
|
||||
_in.read(body);
|
||||
Assert.assertEquals("\nBody\n",new String(body,0,6,StringUtil.__UTF8));
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaderCRLFBodyLF() throws Exception
|
||||
{
|
||||
_queue.add("Header\r\n");
|
||||
_queue.add("\r\n");
|
||||
_queue.add("\nBody\n");
|
||||
_queue.add("\r\n");
|
||||
_queue.add("__CLOSE__");
|
||||
|
||||
Assert.assertEquals("Header",_in.readLine());
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
|
||||
byte[] body = new byte[6];
|
||||
_in.read(body);
|
||||
Assert.assertEquals("\nBody\n",new String(body,0,6,StringUtil.__UTF8));
|
||||
|
||||
Assert.assertEquals("",_in.readLine());
|
||||
Assert.assertEquals(null,_in.readLine());
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue