web-dev-qa-db-fra.com

Envoyer une demande HTTP manuellement via socket

Lorsque j'envoie une requête HTTP normale via un socket, le serveur ne répond pas par 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-t-il pas la requête HTTP lorsque je l'envoie manuellement?

47
Eng.Fouad

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 ( lien ). Alors ajoutez pw.println("");
46
Lycha

Vous ne suivez pas le HTTP RFC .

  • Les lignes d’en-tête se terminent toujours par un CR LF (c.-à-d. 0x0d plus 0x0a).
  • L'en-tête se termine après la première double nouvelle ligne. Dans votre cas, vous n'incluez pas la nouvelle ligne de fin afin que le serveur ne reconnaisse pas la fin des en-têtes de requête.

En règle générale, vous devriez toujours essayer d'utiliser les bibliothèques HTTP existantes. Bien que HTTP semble être un protocole simple (et comparé à d’autres), il a des règles syntaxiques et sémantiques assez strictes. Si vous essayez d'implémenter cela vous-même, vous devriez avoir lu et compris les parties pertinentes de la RFC 2616 (et les textes associés).

Malheureusement, il existe déjà trop d'implémentations HTTP de mauvaise qualité qui ne respectent pas les normes, ce qui rend la vie de tout le monde misérable. Économisez de l'argent et utilisez les bibliothèques HTTP de la langue de votre choix.

22
Holger Just

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

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");
8
TadejP

Le correctif suivant, comme mentionné dans 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
Aimar Hassano