Envoyer une requête HTTP manuellement via socket

Lorsque j'envoie une requête HTTP normale via un socket, le serveur ne répond pas avec une réponse OK. J'ai copié L'en-tête HTTP de FireFox. Voici le code:

Socket s = new Socket(InetAddress.getByName("stackoverflow.com"), 80);
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.print("GET / HTTP/1.1");
pw.print("Host: stackoverflow.com");
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while((t = br.readLine()) != null) System.out.println(t);
br.close();

Cependant, voici la réponse que j'ai reçue:

HTTP/1.0 408 Request Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>

Je sais que je peux le faire en utilisant URL.openStream(), mais pourquoi le serveur n'identifie pas la requête HTTP lorsque je l'envoie manuellement?

39
demandé sur Eng.Fouad 2012-05-20 17:08:12

4 réponses

Deux choses:

  1. Vous devez utiliser println au lieu de print pour imprimer vos entrées sur des lignes séparées.
  2. la requête HTTP doit se terminer par une ligne vide (link ). Alors ajoutez pw.println("");
40
répondu Lycha 2012-05-20 13:29:55

Vous ne suivez pas le HTTP RFC .

  • les lignes D'en-tête sont toujours terminées par un CR LF (c'est-à-dire 0x0d plus 0x0a).
  • l'en-tête se termine après le premier double saut de ligne. Dans votre cas, vous n'incluez pas le retour à la ligne de fin afin que le serveur ne reconnaisse pas la fin des en-têtes de requête.

Généralement, vous devriez toujours essayer d'utiliser les bibliothèques HTTP existantes. Bien que HTTP semble être un protocole simple (et il est comparé aux autres), il a un syntaxique plutôt strict et les règles sémantiques. Si vous essayez de l'implémenter vous-même, vous devriez avoir lu et compris les parties pertinentes de la RFC 2616 (et connexes).

Malheureusement, il y a déjà trop d'implémentations HTTP merdiques qui ne suivent pas les normes qui rendent la vie pour tout le monde misérable. Épargnez-vous les tracas et utilisez les bibliothèques HTTP de votre langue choisie.

22
répondu Holger Just 2012-05-20 13:18:42

Le correctif correct qui fonctionne vraiment et il est multi-plateforme:

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");
8
répondu TadejP 2015-04-05 12:24:59

Le correctif suivant, comme indiqué par les réponses précédentes, résout le problème;

pw.print("GET / HTTP/1.1\n\r\n");
pw.print("Host: stackoverflow.com\n\r\n");
4
répondu Aimar Hassano 2015-03-24 17:11:16