2016-09-07 4 views
0

Как читать HTTP-запрос с помощью InputStream? Я читала это так:Как правильно прочитать HTTP-запрос?

InputStream in = address.openStream(); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
StringBuilder result = new StringBuilder(); 
String line; 
while((line = reader.readLine()) != null) { 
    result.append(line); 
} 
System.out.println(result.toString()); 

Но reader.readLine() может быть заблокирован, потому что нет никакой гарантии, что null линия будет достигнута. Конечно, я могу прочитать заголовок Content-Length, а затем запрос на чтение в цикле:

for (int i = 0; i < contentLength; i++) { 
       int a = br.read(); 
       body.append((char) a); 
    } 

Но если Content-Length установлен слишком большим (я предполагаю, что это может быть установлено вручную для целей), br.read() будет заблокирован. Я стараюсь читать байты непосредственно из InputStream, как это:

byte[] bytes = getBytes(is); 

public static byte[] getBytes(InputStream is) throws IOException { 

      int len; 
      int size = 1024; 
      byte[] buf; 

      if (is instanceof ByteArrayInputStream) { 
       size = is.available(); 
       buf = new byte[size]; 
       len = is.read(buf, 0, size); 
      } else { 
       ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
       buf = new byte[size]; 
       while ((len = is.read(buf, 0, size)) != -1) 
       bos.write(buf, 0, len); 
       buf = bos.toByteArray(); 
      } 
      return buf; 
      } 

Но она ждет навсегда. Что?

+0

Почему нет гарантии, что линия «null» будет достигнута? Согласно документации, он возвращает «null, если конец потока достигнут». Поэтому, если соединение закрыто, вы получите нулевое значение после прочтения последней строки. –

+0

Первая нулевая строка, к которой я могу добраться, - это разделитель между заголовками и объектом запроса (например, данные формы). Но после тела нет нулевой линии. Что? – Tony

+0

Может быть, вы получите запрос с пустым телом? –

ответ

2

Если вы используете HTTP-сервер, вы должны определить конец запроса в соответствии со спецификацией HTTP. Wiki - https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

Прежде всего, вы должны прочитать строку запроса, это всегда одна строка. Затем прочитайте все заголовки запросов. Вы читаете их, пока у вас не будет пустой строки (т. Е. Двух строк: <CR><LF>).

После у вас есть строка состояния и заголовки, вы должны решить, вам нужно прочитать тело или нет, потому что не все запросы могут иметь тело - summary table

Затем, если вам нужно тело, вы должны проанализировать ваши заголовки (который у вас уже есть) и получить Content-Length. Если это - просто прочитайте столько байтов из потока, сколько указано. Когда Content-Length отсутствует, длина определяется другими способами. Кодирование с передачей пакетов использует размер блока размером 0, чтобы отметить конец содержимого. Кодирование идентификатора без Content-Length считывает содержимое до закрытия сокета.

-1

Создайте оболочку запроса, которая расширяет HttpServletRequestWrapper, которая переопределит getInputStream(), которые в свою очередь возвращают ServletInputStream, который имеет безопасный метод чтения. попробуйте, что

+0

Это не связано с сервлетами. – Tony