pythonclientfastcgi

Python fastcgi client


I'm writing a tool on python for monitoring fastcgi application. The only thing I need from fastcgi is to load ping and status pages (and return some kind of error if it fails).

There are a lot of libraries (from python-fasctgi bindings to twisted) which seems to be capable of this, but most of them are simply overkill for my purpose, and many of them will dive me additional dependencies, causing some packaging problems.

So, are there any simple python fastcgi client implementations/libraries which is easy to install/package (to rpm) or small enough to distribute with the project.

UPDATE:

Thanks to agf, I've been able to connect to fastcgi app and send some kind of request to it. It's nothing more than standard php-fpm. But I'm not able to get response for any location: I'm trying to from '/ping', which should respond with 200 OK and 'pong' in body. All I'm getting is 200 OK response with empty body for any my request.

I'm doing request in this way:

def _load_page(self, url):
    """ load fastcgi page """
    fcgi = fcgi_client.FCGIApp(host = self.fcgi_host, port = self.fcgi_port)
    env = {
           'SCRIPT_FILENAME': url,
           'QUERY_STRING': url,
           'REQUEST_METHOD': 'GET',
           'SCRIPT_NAME': url,
           'REQUEST_URI': url,
           'GATEWAY_INTERFACE': 'CGI/1.1',
           'SERVER_SOFTWARE': 'ztc',
           'REDIRECT_STATUS': '200',
           'CONTENT_TYPE': '',
           'CONTENT_LENGTH': '0',
           'DOCUMENT_URI': url,
           'DOCUMENT_ROOT': '/',
           #'SERVER_PROTOCOL' : ???
           'REMOTE_ADDR': '127.0.0.1',
           'REMOTE_PORT': '123',
           'SERVER_ADDR': self.fcgi_host,
           'SERVER_PORT': str(self.fcgi_port),
           'SERVER_NAME': self.fcgi_host
           }
    ret = fcgi(env)
    print ret

I've also had to modify flup client in stdin handling:

# Transfer wsgi.input to FCGI_STDIN
content_length = int(environ.get('CONTENT_LENGTH') or 0)
s = ''
while True:
    chunk_size = min(content_length, 4096)
    #s = environ['wsgi.input'].read(chunk_size)
    content_length -= len(s)
    rec = Record(FCGI_STDIN, requestId)
    rec.contentData = s
    rec.contentLength = len(s)
    rec.write(sock)

    if not s: break

Note added s='' instead of s = environ['wsgi.input'].read(chunk_size), which is part of some wsgi-related stuff from flup. So it should send empty stdin.

Also, I've modified flup to return status, headers, result.

I've checked response reading code and it seems to be fine: there's really empty body from fpm. I've checked network communications with wireshard, and it seems fine for me - all params are being transferred.

Any ideas?

UPDATE:

The problem was with fastcgi param filtering function: it was filtering out a lot of usefull params like DOCUMENT_ROOT, SCRIPT_FILENAME and so on. After disabling this, everything is working well.

For anyone interested, here is the modified client: https://bitbucket.org/rvs/ztc/src/6ec59525156d/src/ztc/lib/flup_fcgi_client.py, and here is usage example: https://bitbucket.org/rvs/ztc/src/6ec59525156d/src/ztc/php/fpm.py


Solution

  • Although flup is primarily used as a fastcgi server, it also includes a fastcgi client.

    http://hg.saddi.com/flup-server/file/tip/flup/client/fcgi_app.py

    It appears to be a single file standalone implementation with no dependencies. It has a permissive license.