forked from I2P_Developers/i2p.i2p
* i2psnark: Support HTTP request ranges so in-browser and other http-aware media players work better.
Single range only; no multipart
This commit is contained in:
@ -23,6 +23,8 @@ import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
@ -318,8 +320,14 @@ class BasicServlet extends HttpServlet
|
||||
out = new WriterOutputStream(response.getWriter());
|
||||
}
|
||||
|
||||
// Write content normally
|
||||
long content_length = content.getContentLength();
|
||||
|
||||
// see if there are any range headers
|
||||
Enumeration reqRanges = request.getHeaders("Range");
|
||||
|
||||
if (reqRanges == null || !reqRanges.hasMoreElements()) {
|
||||
// if there were no ranges, send entire entity
|
||||
// Write content normally
|
||||
writeHeaders(response,content,content_length);
|
||||
if (content_length >= 0 && request.getMethod().equals("HEAD")) {
|
||||
// if we know the content length, don't send it to be counted
|
||||
@ -329,10 +337,32 @@ class BasicServlet extends HttpServlet
|
||||
// GET or unknown size for HEAD
|
||||
copy(in, out);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Parse the satisfiable ranges
|
||||
List<InclusiveByteRange> ranges = InclusiveByteRange.satisfiableRanges(reqRanges, content_length);
|
||||
|
||||
// if there are no satisfiable ranges, send 416 response
|
||||
// Completely punt on multiple ranges (unlike Default)
|
||||
if (ranges == null || ranges.size() != 1) {
|
||||
writeHeaders(response, content, content_length);
|
||||
response.setStatus(416);
|
||||
response.setHeader("Content-Range", InclusiveByteRange.to416HeaderRangeString(content_length));
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is only a single valid range (must be satisfiable
|
||||
// since were here now), send that range with a 216 response
|
||||
InclusiveByteRange singleSatisfiableRange = ranges.get(0);
|
||||
long singleLength = singleSatisfiableRange.getSize(content_length);
|
||||
writeHeaders(response, content, singleLength);
|
||||
response.setStatus(206);
|
||||
response.setHeader("Content-Range", singleSatisfiableRange.toHeaderRangeString(content_length));
|
||||
copy(in, singleSatisfiableRange.getFirst(content_length), out, singleLength);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
|
||||
throws IOException
|
||||
@ -532,11 +562,29 @@ class BasicServlet extends HttpServlet
|
||||
* Write from in to out
|
||||
*/
|
||||
private void copy(InputStream in, OutputStream out) throws IOException {
|
||||
copy(in, 0, out, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write from in to out
|
||||
*/
|
||||
private void copy(InputStream in, long skip, OutputStream out, final long len) throws IOException {
|
||||
ByteArray ba = _cache.acquire();
|
||||
byte[] buf = ba.getData();
|
||||
try {
|
||||
if (skip > 0)
|
||||
in.skip(skip);
|
||||
int read = 0;
|
||||
while ( (read = in.read(buf)) != -1) {
|
||||
long tot = 0;
|
||||
boolean done = false;
|
||||
while ( (read = in.read(buf)) != -1 && !done) {
|
||||
if (len >= 0) {
|
||||
tot += read;
|
||||
if (tot >= len) {
|
||||
read -= (int) (tot - len);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
out.write(buf, 0, read);
|
||||
}
|
||||
} finally {
|
||||
|
@ -16,16 +16,13 @@
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
package org.klomp.snark.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Byte range inclusive of end points.
|
||||
* <PRE>
|
||||
@ -49,8 +46,6 @@ import org.eclipse.jetty.util.log.Logger;
|
||||
*/
|
||||
public class InclusiveByteRange
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(InclusiveByteRange.class);
|
||||
|
||||
long first = 0;
|
||||
long last = 0;
|
||||
|
||||
@ -76,11 +71,11 @@ public class InclusiveByteRange
|
||||
/**
|
||||
* @param headers Enumeration of Range header fields.
|
||||
* @param size Size of the resource.
|
||||
* @return LazyList of satisfiable ranges
|
||||
* @return List of satisfiable ranges
|
||||
*/
|
||||
public static List satisfiableRanges(Enumeration headers, long size)
|
||||
public static List<InclusiveByteRange> satisfiableRanges(Enumeration headers, long size)
|
||||
{
|
||||
Object satRanges=null;
|
||||
List<InclusiveByteRange> satRanges = null;
|
||||
|
||||
// walk through all Range headers
|
||||
headers:
|
||||
@ -105,7 +100,6 @@ public class InclusiveByteRange
|
||||
{
|
||||
if ("bytes".equals(t))
|
||||
continue;
|
||||
LOG.warn("Bad range format: {}",t);
|
||||
continue headers;
|
||||
}
|
||||
else if (d == 0)
|
||||
@ -114,7 +108,6 @@ public class InclusiveByteRange
|
||||
last = Long.parseLong(t.substring(d + 1).trim());
|
||||
else
|
||||
{
|
||||
LOG.warn("Bad range format: {}",t);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -134,25 +127,23 @@ public class InclusiveByteRange
|
||||
|
||||
if (first < size)
|
||||
{
|
||||
if (satRanges == null)
|
||||
satRanges = new ArrayList(4);
|
||||
InclusiveByteRange range = new InclusiveByteRange(first,last);
|
||||
satRanges = LazyList.add(satRanges,range);
|
||||
satRanges.add(range);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
LOG.warn("Bad range format: {}",t);
|
||||
LOG.ignore(e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.warn("Bad range format: {}",t);
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
return LazyList.getList(satRanges,true);
|
||||
return satRanges;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -1,3 +1,12 @@
|
||||
2013-04-28 zzz
|
||||
* i2psnark:
|
||||
- Improve page nav
|
||||
- Ensure current stats and correct event delivered in announce
|
||||
- Only show lower section on first page
|
||||
- Dir page CSS tweaks
|
||||
- Parameter fixes
|
||||
- Support HTTP request ranges
|
||||
|
||||
2013-04-26 zzz
|
||||
* Console: Show log location on /logs even if not opened yet (ticket #905)
|
||||
* HTTP proxy: Verify nonce count in digest auth
|
||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 18;
|
||||
public final static long BUILD = 19;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user