2011-06-30 2 views
0

Je suis relativement nouveau à Python mais j'ai fait beaucoup de choses avec ça récemment et je l'aime beaucoup. Cependant, j'ai rencontré des problèmes/bloc avec le code suivant.html dans la méthode do_GET() d'un simple serveur web Python

import http.server 
import socketserver 
import glob 
import random 
class Server(http.server.SimpleHTTPRequestHandler): 
    def do_GET(self): 
     self.send_response(200, 'OK') 
     self.send_header('Content-type', 'html') 
     self.end_headers() 
     self.wfile.write(bytes("<html> <head><title> Hello World </title> </head> <body>", 'UTF-8')) 
     images = glob.glob('*.jpg') 
     rand = random.randint(0,len(images)-1) 
     imagestring = "<img src = \"" + images[rand] + "\" height = 1028 width = 786 align = \"right\"/> </body> </html>" 
     self.wfile.write(bytes(imagestring, 'UTF-8')) 

    def serve_forever(port): 
     socketserver.TCPServer(('', port), Server).serve_forever() 
if __name__ == "__main__": 
    Server.serve_forever(8000) 

Ce que je suis en train de faire ici est de saisir une image aléatoire à partir de plusieurs images dans le répertoire et l'ajouter dans la réponse à une requête Web. Le code fonctionne correctement mais lorsque j'accède au serveur via le navigateur, l'image n'est pas affichée. Le html de la page est comme prévu cependant. Les autorisations sur les fichiers sont 755. J'ai également essayé de créer un fichier index.html dans la méthode do_GET. Cela n'a pas fonctionné non plus. Je veux dire que l'index.html a été généré correctement, mais la réponse dans le navigateur n'a pas montré quoi que ce soit (pas même le monde de Hello dans le titre). Est-ce que je manque quelque chose de très simple ici? Je pensais que je devrais surcharger le handle_request du SocketServer.BaseServer sous-jacent comme la documentation dit que vous ne devriez jamais surcharger la méthode handle() de BaseHTTPServer et devrait plutôt remplacer la méthode do_ * correspondante?

Répondre

0

Je suppose que lorsque le navigateur envoie à votre serveur la demande pour l'image que vous avez mise dans le code HTML, vous lui envoyez le code HTML pour une autre page. Vous devez probablement ajouter une vérification au début de votre do_GET pour vous assurer que ce n'est pas une requête pour l'image (ou une requête pour une page particulière).

+0

En ce qui concerne les images, je pense que le serveur envoie l'image sous forme de données binaires dans la même connexion TCP ou dans une connexion TCP différente (selon que vous utilisez un HTTP persistant ou non persistant). Dans les deux cas, l'image est enroulée autour des en-têtes HTTP habituels. Mais je vois votre point de vue, il doit encore envoyer le fichier image. Si vous voyez les réponses du serveur dans le terminal, vous pouvez voir qu'il répond avec un 200 pour les demandes de fichiers d'image. –

+0

Que se passe-t-il lorsque vous wget/curl l'URL de l'image telle que servie par votre script (c'est-à-dire, celle vers laquelle vous naviguez dans le navigateur)? Le fichier résultant est-il visible en tant qu'image ou ressemble-t-il au code HTML lorsque vous l'ouvrez dans un éditeur de texte? – Sasha

+0

Bien en utilisant wget/curl, il envoie simplement html. Une enquête plus approfondie utilisant tcpflow et lisant les messages transmis sur l'interface de bouclage, j'ai constaté que le serveur n'envoie pas réellement l'image (en tant que données binaires). Ce que je vois est la deuxième requête du navigateur pour l'image. Maintenant, je pourrais vérifier la demande entrante comme une demande pour une des images mais le problème est comment réellement envoyer l'image sur le fil? Il s'avère que http.server n'a aucune méthode de codage. Une lecture plus approfondie me pointe vers l'utilisation de httplib. –

1

Oh, vous mélangez beaucoup de " et \" dans cette ligne:

"<img src = \" + images[rand] + '\" height = 1028 width = 786 align = \"right\"/> </body> </html>'

Il devrait probablement:

'<img src = "' + images[rand] + '" height = 1028 width = 786 align="right"/> </body> </html>' 

Sinon, vous ne serez pas obtenir l'image, mais le texte "images[rand]"!

+0

Je suis désolé.Dans le code actuel, il est: imagestring = "" –

+1

En passant, composer du HTML en Python comme ceci est toujours méchant et je ne le recommande pas aux non-cyborgs. À des fins simples, la bibliothèque standard Python fournit un système de modèle simple appelé chaînes de modèles: http://docs.python.org/library/string.html#template-strings. Pour les projets non-triviaux, vous pourriez vouloir utiliser un vrai moteur de template (comme Jinja2, Cheetah, etc.). Les deux approches seraient plus lisibles et élimineraient les problèmes d'échappement comme les backslashes. – Sasha

4

J'ai changé le code:

#!usr/bin/python3.2 
import http.server 
import socketserver 
import glob 
import random 
import sys 

class Server(http.server.SimpleHTTPRequestHandler): 
def do_GET(self): 
    referer = self.headers.get('Referer') 
    print("The referer is", referer) 
    if referer == None: 
     self.protocol_version='HTTP/1.1' 
     self.send_response(200, 'OK') 
     self.send_header('Content-type', 'text/html') 
     self.end_headers() 
     self.wfile.write(bytes("<html> <head><title> Hello World </title> </head> <body>", 'UTF-8')) 
     images = glob.glob('*.jpg') 
     rand = random.randint(0,len(images)-1) 
     filepath = images[rand] 
     imagestring = "<img src = \"" + images[rand] + "\" height = 1028 width = 786 align = \"right\"/> </body> </html>" 
     self.wfile.write(bytes(imagestring, 'UTF-8')) 
    else: 
     imgname = self.path 
     print ("Image requested is: ", imgname[1:]) 
     imgfile = open(imgname[1:], 'rb').read() 
     self.send_header('Content-type', 'image/jpeg') 
     self.send_header('Content-length', sys.getsizeof(imgfile)) 
     self.end_headers() 
     self.wfile.write(imgfile) 

def serve_forever(port): 
    socketserver.TCPServer(('', port), Server).serve_forever() 

if __name__ == "__main__": 
    Server.serve_forever(8000) 

Avec tcpflow, je peux voir l'image envoyée sous forme de données binaires sur le fil, mais je ne vois toujours pas d'image dans le navigateur.

+0

Ceci n'est pas une réponse à votre question. Vous devriez éditer votre question pour inclure cette information. –

+0

cela a fonctionné pour moi! – mbdavis

0

J'ai un code très similaire à votre version modifiée (la version affichée en guise de réponse) qui fonctionne pour moi. La seule différence est que je n'envoie pas la longueur du contenu, alors peut-être que c'est la cause de votre problème.

Questions connexes