📄 httpinputstreamreader.java
字号:
while (!lineRead) {
b = inputStream.read();
switch (b) {
case EOS:
// We've finished reading the stream, and so the line is
// finished too.
if (len == 0) {
return null;
}
lineRead = true;
break;
/*
* if (len > 0) { ret = new byte[len]; System.arraycopy(buf, 0,
* ret, 0, len); return ret; } return null;
*/
case LF:
// We found the end of the current line.
lineRead = true;
break;
case CR:
// We got a CR. It can be the end of line.
// Is it followed by a LF ? (not mandatory in RFC 2616)
b = inputStream.read();
if (b != LF) {
// The end of line was a simple LF: the next one blongs
// to the next line.
inputStream.unread(b);
}
lineRead = true;
break;
default:
buf[len++] = (byte) b;
// If the buffer is too small, we let enough space to add CR
// and LF, in case of ...
if (len + 2 >= buflen) {
buflen *= 2;
byte[] tmp = new byte[buflen];
System.arraycopy(buf, 0, tmp, 0, len);
buf = tmp;
}
}
} // while
// Let's go back to before any CR and LF.
while (len > 0 && (buf[len] == CR || buf[len] == LF)) {
len -= 1;
}
// Ok, now len indicates the end of the actual line.
// Should we add a proper CRLF, or nothing ?
if (includeCR) {
// We have enough space to add these two characters (see the default
// here above)
buf[len++] = CR;
buf[len++] = LF;
}
if (len > 0) {
ret = new byte[len];
if (len > 0)
System.arraycopy(buf, 0, ret, 0, len);
} else {
// line feed for empty line between headers and body, or within the
// body.
ret = new byte[0];
}
return ret;
}
/**
* Read the headers from the given input stream.
*
* @param httpDataIn The http input stream
* @throws IOException
* @throws JUploadException
*/
private void readHeaders(PushbackInputStream httpDataIn)
throws IOException, JUploadException {
StringBuffer sbHeaders = new StringBuffer();
// Headers are US-ASCII (See RFC 2616, Section 2.2)
String tmp;
while (!this.httpConnectionHelper.gotStopped()) {
tmp = readLine(httpDataIn, "US-ASCII", false);
if (null == tmp)
throw new JUploadException("unexpected EOF (in header)");
if (this.httpStatusCode == 0) {
// We must be reading the first line of the HTTP header.
this.uploadPolicy.displayDebug(
"-------- Response Headers Start --------", 80);
Matcher m = pHttpStatus.matcher(tmp);
if (m.matches()) {
this.httpStatusCode = Integer.parseInt(m.group(2));
this.responseMsg = m.group(1);
} else {
// The status line must be the first line of the
// response. (See RFC 2616, Section 6.1) so this
// is an error.
// We first display the wrong line.
this.uploadPolicy.displayDebug("First line of response: '"
+ tmp + "'", 80);
// Then, we throw the exception.
throw new JUploadException(
"HTTP response did not begin with status line.");
}
}
// Handle folded headers (RFC 2616, Section 2.2). This is
// handled after the status line, because that line may
// not be folded (RFC 2616, Section 6.1).
if (tmp.startsWith(" ") || tmp.startsWith("\t"))
this.line += " " + tmp.trim();
else
this.line = tmp;
// The read line is now correctly formatted.
this.uploadPolicy.displayDebug(this.line, 80);
sbHeaders.append(tmp).append("\n");
if (pClose.matcher(this.line).matches())
this.gotClose = true;
if (pProxyClose.matcher(this.line).matches())
this.gotClose = true;
if (pChunked.matcher(this.line).matches())
this.gotChunked = true;
Matcher m = pContentLen.matcher(this.line);
if (m.matches()) {
this.gotContentLength = true;
this.clen = Integer.parseInt(m.group(1));
}
m = pContentTypeCs.matcher(this.line);
if (m.matches())
this.charset = m.group(1);
m = pSetCookie.matcher(this.line);
if (m.matches()) {
this.uploadPolicy.displayDebug(
"Calling this.cookies.parseCookieHeader, with parameter: "
+ m.group(1), 80);
this.cookies.parseCookieHeader(m.group(1));
this.uploadPolicy.displayDebug("Cookie header parsed.", 80);
}
if (this.line.length() == 0) {
// We've finished reading the headers
break;
}
}
// RFC 2616, Section 6. Body is separated by the
// header with an empty line.
this.responseHeaders = sbHeaders.toString();
this.uploadPolicy.displayDebug(
"--------- Response Headers End ---------", 80);
}// readHeaders()
/**
* Read the body from the given input stream.
*
* @param httpDataIn The http input stream
* @throws IOException
* @throws JUploadException
* @throws JUploadException
*/
private void readBody(PushbackInputStream httpDataIn) throws IOException,
JUploadException {
// && is evaluated from left to right so !stop must come first!
while (!this.httpConnectionHelper.gotStopped()
&& ((!this.gotContentLength) || (this.clen > 0))) {
if (this.gotChunked) {
// Read the chunk header.
// This is US-ASCII! (See RFC 2616, Section 2.2)
this.line = readLine(httpDataIn, "US-ASCII", false);
if (null == this.line)
throw new JUploadException(
"unexpected EOF (in HTTP Body, chunked mode)");
// Handle a single chunk of the response
// We cut off possible chunk extensions and ignore them.
// The length is hex-encoded (RFC 2616, Section 3.6.1)
int len = Integer.parseInt(this.line.replaceFirst(";.*", "")
.trim(), 16);
this.uploadPolicy.displayDebug("Chunk: " + this.line + " dec: "
+ len, 70);
if (len == 0) {
// RFC 2616, Section 3.6.1: A length of 0 denotes
// the last chunk of the body.
// This code wrong if the server sends chunks
// with trailers! (trailers are HTTP Headers that
// are send *after* the body. These are announced
// in the regular HTTP header "Trailer".
// Fritz: Never seen them so far ...
// TODO: Implement trailer-handling.
break;
}
// Loop over the chunk (len == length of the chunk)
while (len > 0) {
int rlen = (len > CHUNKBUF_SIZE) ? CHUNKBUF_SIZE : len;
int ofs = 0;
if (rlen > 0) {
while (ofs < rlen) {
int res = httpDataIn.read(this.chunkbuf, ofs, rlen
- ofs);
if (res < 0)
throw new JUploadException("unexpected EOF");
len -= res;
ofs += res;
}
if (ofs < rlen)
throw new JUploadException("short read");
if (rlen < CHUNKBUF_SIZE)
this.body = byteAppend(this.body, this.chunkbuf,
rlen);
else
this.body = byteAppend(this.body, this.chunkbuf);
}
}
// Got the whole chunk, read the trailing CRLF.
readLine(httpDataIn, false);
} else {
// Not chunked. Use either content-length (if available)
// or read until EOF.
if (this.gotContentLength) {
// Got a Content-Length. Read exactly that amount of
// bytes.
while (this.clen > 0) {
int rlen = (this.clen > CHUNKBUF_SIZE) ? CHUNKBUF_SIZE
: this.clen;
int ofs = 0;
if (rlen > 0) {
while (ofs < rlen) {
int res = httpDataIn.read(this.chunkbuf, ofs,
rlen - ofs);
if (res < 0)
throw new JUploadException(
"unexpected EOF (in HTTP body, not chunked mode)");
this.clen -= res;
ofs += res;
}
if (ofs < rlen)
throw new JUploadException("short read");
if (rlen < CHUNKBUF_SIZE)
this.body = byteAppend(this.body,
this.chunkbuf, rlen);
else
this.body = byteAppend(this.body, this.chunkbuf);
}
}
} else {
// No Content-length available, read until EOF
//
while (true) {
byte[] lbuf = readLine(httpDataIn, true);
if (null == lbuf)
break;
this.body = byteAppend(this.body, lbuf);
}
break;
}
}
} // while
// Convert the whole body according to the charset.
// The default for charset ISO-8859-1, but overridden by
// the charset attribute of the Content-Type header (if any).
// See RFC 2616, Sections 3.4.1 and 3.7.1.
this.responseBody = new String(this.body, this.charset);
// At the higher debug level, we display the response.
this.uploadPolicy.displayDebug("-------- Response Body Start --------",
100);
this.uploadPolicy.displayDebug(this.responseBody, 100);
this.uploadPolicy.displayDebug("-------- Response Body End --------",
100);
}// readBody
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -