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?
4 réponses
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
plus0x0a
). - 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.
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");
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");