Неверный запрос HTTP-клиента 400

Я пытаюсь узнать, как HTTP-клиент работает на Java. Я пытаюсь создать свой собственный клиент, который будет запрашивать на веб-сервере файл php.

В настоящее время, когда я делаю запрос, сервер выдает мне следующую ошибку:

HTTP / 1.1 400 неверный запрос

Однако я могу получить доступ к файлу из браузера без проблем. Я не знаю, что я делаю не так, но я не могу этого понять. Ниже приведен код моего класса HTTP-клиента:

public class MyHttpClient {

MyHttpRequest request;
String host;

public MyHttpResponse execute(MyHttpRequest request) throws IOException {

    //Creating the response object
    MyHttpResponse response = new MyHttpResponse();

    //Get web server host and port from request.
    String host = request.getHost();
    int port = request.getPort();

    //Check 1: HOST AND PORT NAME CORRECT!
    System.out.println("host: " + host + " port: " + String.valueOf(port));

    //Get resource path on web server from requests.
    String path = request.getPath();

    //Check 2: ENSURE PATH IS CORRECT!
    System.out.println("path: " + path);

    //Open connection to the web server
    Socket s = new Socket(host, port);

    //Get Socket input stream and wrap it in Buffered Reader so it can be read line by line.
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));

    //Get Socket output stream and wrap it in a Buffered Writer so it can be written to line by line.
    PrintWriter outToServer = new PrintWriter(s.getOutputStream(),true);

    //Get request method
    String method = request.getMethod();

    //Check 3: ENSURE REQUEST IS CORRECT GET/POST!
    System.out.println("Method: " + method);

    //GET REQUEST
    if(method.equalsIgnoreCase("GET")){
        //Send request to server
        outToServer.println("GET " + path + " HTTP/1.1 " + "\r\n");
        String line = inFromServer.readLine();
        System.out.println("Line: " + line);
    }

    //Returning the response
    return response;
}

}

Если бы кто-нибудь мог пролить свет на эту проблему, я был бы очень признателен! Спасибо.

Новый запрос к серверу:

outToServer.print("GET " + path+ " HTTP/1.1" + "\r\n");
outToServer.print("Host: " + host + "\r\n");
outToServer.print("\r\n");

Ответ:

Метод: ПОЛУЧИТЬ

line: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
line: <html><head>
line: <title>400 Bad Request</title>
line: </head><body>
line: <h1>Bad Request</h1>
line: <p>Your browser sent a request that this server could not understand.<br />
line: </p>
line: <hr>
line: <address>Apache Server at default.secureserver.net Port 80</address>
line: </body></html>
line: null

person Javacadabra    schedule 28.01.2013    source источник


Ответы (2)


Не используйте PrintWriter. Вы должны писать символы ascii.

 s.getOutputStream().write(("GET " + path + " HTTP/1.1\r\n\r\n").getBytes("ASCII"));
person jdb    schedule 29.01.2013
comment
Извините, пропустил способ - пишите - person jdb; 29.01.2013
comment
ФИКСИРОВАННЫЙ!! Большое спасибо! Я работал над этим весь день. - person Javacadabra; 29.01.2013

Думаю нужно хотя бы добавить в запрос заголовок Host.

Пример взят из http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

GET /index.html HTTP/1.1
Host: www.example.com

После завершения заголовков вам также необходимо передать дополнительный \r\n, чтобы сервер знал, что запрос завершен.

Не используйте println, но print. println добавляет еще \n к каждой строке, в результате чего строки заканчиваются на \r\n\n.

person bikeshedder    schedule 28.01.2013
comment
Я скорректировал запрос, как вы упомянули, вот так: outToServer.println("GET " + path + " HTTP/1.1 " + "\r\n"); outToServer.println("Host: " + host); outToServer.println("\r\n");, но все еще получаю ошибку. - person Javacadabra; 29.01.2013
comment
Ты забыл еще один \r\n. Заголовок хоста заканчивается \r\n, а затем блок заголовка должен завершаться \r\n. - person bikeshedder; 29.01.2013
comment
Спасибо, теперь он работает, но первая строка, которую я возвращаю, не является кодом состояния? Это нормально? Я ожидал что-то вроде GET 200 OK, вместо этого я получаю html - person Javacadabra; 29.01.2013
comment
Не используйте println, а используйте print. Println добавляет еще \n, поэтому вы получаете \r\n\n, который, вероятно, вызывает ошибку. - person bikeshedder; 29.01.2013
comment
Я предполагаю, что сервер читает ваш запрос как запрос HTTP / 0.9. Ответы HTTP / 0.9 не обязательно включают заголовки. - person bikeshedder; 29.01.2013
comment
Я внес изменения, я включил их в свой исходный вопрос внизу. По какой-то причине кажется, что моя программа зависает на долгое время и не получает ответа от сервера. - person Javacadabra; 29.01.2013
comment
Обязательно вызовите flush (), как только закончите отправку запроса: PrintStream.flush - person bikeshedder; 29.01.2013
comment
о, хорошо, я звоню сейчас и получаю какой-то ответ, и это хорошие новости! Я включил это в исходный вопрос. Возможно, вы правы, когда говорите, что сервер может неправильно интерпретировать запросы. - person Javacadabra; 29.01.2013
comment
Ой, я пропустил, что вы использовали PrintWriter. Однако вам не нужно работать с необработанным OutputStream. Не могли бы вы попробовать передать третий аргумент конструктору PrintWriter: new PrintWriter(s.getOutputStream(), true, "ASCII"). UTF-8 вместо ASCII тоже должно работать. - person bikeshedder; 29.01.2013
comment
Я попробую это позже! Спасибо. - person Javacadabra; 29.01.2013