Lista ristoranti Parigi e Roma

  • l’Ambassade d’Auvergne
    22, rue du Grenier Saint-Lazare 75003 Paris +33 (0)1 42 72 31 22
  • Louis XIV – rue St. Denis, Paris 10e
  • Brasserie Flo
    7 cour des Petites Ecuries – 75010 Paris
    Tél : +33 (0)1 47 70 13 59
    Open 7D/7 from 12.00 pm to 3.00 pm and from 7.00 pm to 11.00 pm (on Friday and Saturday until 12.00 am).
  • Epicure
    112 rue du Faubourg Saint Honoré
    75008 Paris
    +33 (0)1 53 43 43 40
    Chef des cuisines : Eric Frechon
    Chef Pâtissier : Laurent Jeannin
    Chef sommelier : Marco Pelletier
    Directeur du restaurant : Frédéric Kaiser
  • Le grande Ourse
    9 Rue Georges Saché – 75014 Paris
  • Comptoir de la Gastronomie
    34 Rue Montmartre (Louvre)
    du lundi au jeudi de 12h à 23h.
    les vendredi et samedi de 12h à Minuit.
  • Perilli
  • Antico falcone (trionfale)
    Via Trionfale, 60, 195 Roma, Italia
    Telefono:+39 06 3973 6404
  • Ulisse
    Via Giuseppe Ferrari 10 – 00195 Roma
    Tel.: 06 3217505
    Chiuso il mercoledì
    info@ristoranteulisse.it
  • Nello l’ abruzzese
    Via Monte Santo, 19 – 00195 Roma
    (+39) 06.37.51.74.00
    Pranzo: dalle 12:45 alle 15:30
    Cena: dalle 19:45 alle 23:00
    Domenica riposo settimanale
  • Cuccurucù
    V. CAPOPRATI 10 – 00135 ROMA (RM)

Un proxy basilare con Twisted Python

ho rielaborato questo esempio: http://stackoverflow.com/questions/6491932/need-help-writing-a-twisted-proxy

Nello script definisco alcune classi in un ordine ben preciso, per evitare errori di tipo
NameError: name ‘NomeDellaClasse’ is not defined.

Per capire come si imposta il proxy, iniziamo dalla classe proxy.Proxy:
questa eredita da twisted.web.http.HTTPChannel, e la documentazione spiega che per avviare il reactor bisogna chiamare la factory http.HTTPFactory(), dopodichè segnalare alla factory quale classe derivata da proxy.Proxy usare:

class MyProxy(proxy.Proxy):
    pass

f = http.HTTPFactory()
f.protocol = MyProxy
reactor.listenTCP(8888, f)
try:
	reactor.run()
except KeyboardInterrupt:
	reactor.stop()

Questo script definisce un proxy perfettamente funzionante.
Ma mancano varie funzionalità: queste sono definite nei metodi delle varie classi del modulo proxy.

Per usare le altre classi bisogna ridefinirle (override), a cominciare proprio da Proxy:

Proxy

nel suo codice sorgente si vede che c’è la variabile requestFactory, per specificare quale ProxyRequest usare.

ProxyRequest

Ridefinendo proxy.ProxyRequest abbiamo a disposizione i metodi per manipolare le richieste HTTP.
Dal suo codice sorgente si vedono 2 parametri da specificare, protocols e ports.
Il metodo ProxyRequest.process() crea la richiesta:
come si può vedere, le proprietà protocols e ports vengono usate per creare la clientFactory

class ProxyRequest(Request):
    protocols = {'http': ProxyClientFactory}
    ports = {'http': 80}
    ...
    def process(self):
        parsed = urlparse.urlparse(self.uri)
        protocol = parsed[0]
        host = parsed[1]
        port = self.ports[protocol]
        ...
        class_ = self.protocols[protocol]
        clientFactory = class_(self.method, rest, self.clientproto, headers,
                               s, self)
        self.reactor.connectTCP(host, port, clientFactory)

ProxyClientFactory

Con il protocollo MyProxyClientFactory registrato in MyProxyRequest, si gestisce la parte client del proxy, cioè le risposte http.
Ridefinendo ProxyClientFactory si può specificare una classe figlia di ProxyClient.

ProxyClient

Ridefinendo ProxyClient si ha accesso ai metodi per manipolare le risposte.
Vedere il codice sorgente o la documentazione.

Notare che è necessario richiamare gli handler della classe genitrice !

Esempio

Tutto quanto detto finora si traduce nel seguente script:

""" file myproxy.py """
from twisted.web import http, proxy
from twisted.internet import reactor
from twisted.python import log
import sys

""" Salvo lo stdout prima di avviare il logging di twisted """
schermo = sys.stdout

log.startLogging(open('myproxy.log', 'w'))

class MyProxyClient(proxy.ProxyClient):
	def handleHeader(self, key, value):
		s = "Ricevuto header: " + key
		s+= ", " + value
		schermo.write(s + "\n")
		# richiamare il metodo della classe genitrice
		proxy.ProxyClient.handleHeader(self, key, value)

class MyProxyClientFactory(proxy.ProxyClientFactory):
	protocol = MyProxyClient

class MyProxyRequest(proxy.ProxyRequest):
	protocols = {'http': MyProxyClientFactory}
	ports = {'http': 80}

# non è necessario:
#	def process(self):
#		proxy.ProxyRequest.process(self)

class MyProxy(proxy.Proxy):
	requestFactory = MyProxyRequest


f = http.HTTPFactory()
f.protocol = MyProxy
reactor.listenTCP(8888, f)

try:
	reactor.run()
except KeyboardInterrupt:
	reactor.stop()

Il framework Twisted (Python)

appunti su Twisted tratti da Jp Calderone

Uno script “minimo” basato su Twisted ha bisogno di 3 cose:

  1. una resource: crea i contenuti e li “porta” nel protocollo HTTP
  2. una factory: mette in contatto la porta in ascolto con il protocollo HTTP che serve i contenuti
  3. il reactor: è il controllore di tutto il processo, accetta le connessioni TCP e gestisce l’ input/output dei dati

Quindi la struttura di uno script è la seguente:

resource = SomeResourceClass(params....)
factory = SomeFactoryClass(resource)
reactor.listenTCP(int(port_number), factory)
reactor.run()

Esempio 1: generare un contenuto statico

http://jcalderone.livejournal.com/47954.html

from twisted.web.server import Site # importo la factory che genera un "sito"
from twisted.web.static import File #importo la resource che genera pagine in base al filesystem
from twisted.internet import reactor

resource = File('/tmp')
factory = Site(resource)
reactor.listenTCP(8888, factory)
try:
    reactor.run()
except KeyboardInterrupt:
    reactor.stop()

Esempio 2: generare un contenuto statico con diverse URL

http://jcalderone.livejournal.com/48795.html

from twisted.web.server import Site #la factory
from twisted.web.resource import Resource # una resource "vuota"
from twisted.web.static import File #la resource che genera contenuti
from twisted.internet import reactor

root = Resource()
# le resource che rispondono alle URL foo bar e baz mostrano i contenuti di diverse directory
#vengono "appese" alla risorsa root, che diventa così una struttura ad albero
root.putChild("foo", File("/tmp"))
root.putChild("bar", File("/lost+found"))
root.putChild("baz", File("/opt"))

factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()

Esempio 3: generare un contenuto dinamico

http://jcalderone.livejournal.com/48953.html

from twisted.web.server import Site # factory
from twisted.web.resource import Resource #resource
from twisted.internet import reactor

from calendar import calendar # il calendario di python

class YearPage(Resource): # override di una Resource, sarà la figlia di Calendar
    def __init__(self, year):
        Resource.__init__(self)
        self.year = year
    # questo metodo viene chiamato dopo una richiesta GET
    def render_GET(self, request): # qui si genera il contenuto
        return "<html><body><pre>%s</pre></body></html>" % (calendar(self.year),)

class Calendar(Resource): #override di una Resource
  def getChild(self, name, request):
      return YearPage(int(name))

root = Calendar()
factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()

Esempio 4: risposte asincrone con Deferred

http://jcalderone.livejournal.com/51109.html

from twisted.internet.task import deferLater # subclass di defer.Deferred
from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor

class DelayedResource(Resource):
    def _delayedRender(self, request): # viene chiamata come callback da render_GET
        request.write("Sorry to keep you waiting.") # crea un contenuto
        request.finish() # lo invia come risposta

    def render_GET(self, request): # risposta a GET
        d = deferLater(reactor, 5, lambda: request) # si crea il deferred
        d.addCallback(self._delayedRender) # gli si assegna una callback
        return NOT_DONE_YET # diciamo a render di non produrre adesso la risposta

resource = DelayedResource()

libmproxy: percorso delle request

  1. Nel main di uno script che usa libmproxy si crea un oggetto “Master” che riceve un “server” come parametro:
    # posso estendere controller.Master oppure flow.FlowMaster
    # dipende se voglio le funzioni estese di FlowMaster o meno
    class MyMaster(controller.Master)
        def handle_request(msg):
            msg.reply()
        def handle_response(msg):
            msg.reply()
    
    config=proxy.ProxyConfig()
    server=proxy.ProxyServer(config, 8081)
    m=MyMaster(server)
    m.run()
    
  2. il metodo run() di controller.Master chiama la funzione
    # self.server è una istanza di proxy.ProxyServer !
    self.server.start_slave(Slave, Channel(self.masterq))
    

    che è definita nella classe genitrice di proxy.ProxyServer

  3. in proxy.ProxyServer trovo:
        def start_slave(self, klass, channel):
            slave = klass(channel, self)
            slave.start()
    
  4. la classe Slave definisce un thread che in run() chiama la funzione self.server.serve_forever(), a sua volta definito nella classe genitrice di ProxyServer: netlib/tcp.TCPServer
    class Slave(threading.Thread):
        """
            Slaves get a channel end-point through which they can send messages to
            the master.
        """
        def __init__(self, channel, server):
            self.channel, self.server = channel, server
            self.server.set_channel(channel)
            threading.Thread.__init__(self)
    
        def run(self):
            self.server.serve_forever()
    
  5. in netlib/tcp.py si trova la classe TCPServer con il suo metodo serve_forever:
    questo chiama la funzione self.request_thread in un thread

        def serve_forever(self, poll_interval=0.1):
            self.__is_shut_down.clear()
            try:
                while not self.__shutdown_request:
                    try:
                        r, w, e = select.select([self.socket], [], [], poll_interval)
                    except select.error, ex:
                            if ex[0] == 4:
                                continue
                            else:
                                raise  
                    if self.socket in r:
                        request, client_address = self.socket.accept()
                        t = threading.Thread(
                                target = self.request_thread,
                                args = (request, client_address)
                            )
                        t.setDaemon(1)
                        t.start()
            finally:
                self.__shutdown_request = False
                self.__is_shut_down.set()
    
  6. self.request_thread chiama altri handler:
        def request_thread(self, request, client_address):
            try:
                self.handle_connection(request, client_address)
                request.close()
            except:
                self.handle_error(request, client_address)
                request.close()
        def handle_error(self, request, client_address, fp=sys.stderr):
            """
                Called when handle_connection raises an exception.
            """
            # If a thread has persisted after interpreter exit, the module might be
            # none.
            if traceback:
                exc = traceback.format_exc()
                print >> fp, '-'*40
                print >> fp, "Error in processing of request from %s:%s"%client_addr
    ess
                print >> fp, exc
                print >> fp, '-'*40
    
        def handle_connection(self, request, client_address): # pragma: no cover
            """
                Called after client connection.
            """
            raise NotImplementedError
    
  7. handle_connection viene definita da ProxyServer:
        def handle_connection(self, request, client_address):
            h = ProxyHandler(self.config, request, client_address, self, self.channel, self.server_version)
            h.handle()
            h.finish()
    
  8. la classe ProxyHandler gestisce le connessioni a basso livello.

        def handle(self):
            cc = flow.ClientConnect(self.client_address)
            self.log(cc, "connect")
            self.channel.ask("clientconnect", cc)
            while self.handle_request(cc) and not cc.close:
                pass
            cc.close = True
            self.del_server_connection()
    
            cd = flow.ClientDisconnect(cc)
            self.log(
                cc, "disconnect",
                [
                    "handled %s requests"%cc.requestcount]
            )
            self.channel.tell("clientdisconnect", cd)
        def handle_request(self, cc):
            try:
                request, err = None, None
                request = self.read_request(cc)
                if request is None:
                    return
                cc.requestcount += 1
    
                request_reply = self.channel.ask("request", request)
                if request_reply is None or request_reply == KILL:
                    return
                elif isinstance(request_reply, flow.Response):
                    request = False
                    response = request_reply
                    response_reply = self.channel.ask("response", response)
                else:
                    request = request_reply
                    ...
            except (IOError, ProxyError, http.HttpError, tcp.NetLibError), e:
                ...
    

    il ProxyServer legge la richiesta dal client e la immette nel “canale”, da cui si aspetta la risposta:
    request_reply = self.channel.ask(“request”, request)