def handle_request(self, request): if request.command != 'GET': request.error (400) # bad request return path, params, query, fragment = request.split_uri() if '%' in path: path = http_server.unquote(path) # strip off all leading slashes while path and path[0] == '/': path = path[1:] path, process_name_and_channel = path.split('/', 1) try: process_name, channel = process_name_and_channel.split('/', 1) except ValueError: # no channel specified, default channel to stdout process_name = process_name_and_channel channel = 'stdout' from supervisor.options import split_namespec group_name, process_name = split_namespec(process_name) group = self.supervisord.process_groups.get(group_name) if group is None: request.error(404) # not found return process = group.processes.get(process_name) if process is None: request.error(404) # not found return logfile = getattr(process.config, '%s_logfile' % channel, None) if logfile is None or not os.path.exists(logfile): # we return 404 because no logfile is a temporary condition. # if the process has never been started, no logfile will exist # on disk. a logfile of None is also a temporay condition, # since the config file can be reloaded. request.error(404) # not found return mtime = os.stat(logfile)[stat.ST_MTIME] request['Last-Modified'] = http_date.build_http_date(mtime) request['Content-Type'] = 'text/plain;charset=utf-8' # the lack of a Content-Length header makes the outputter # send a 'Transfer-Encoding: chunked' response request['X-Accel-Buffering'] = 'no' # tell reverse proxy server (e.g., nginx) to disable proxy buffering # (see also http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering) request.push(tail_f_producer(request, logfile, 1024)) request.done()
def handle_request(self, request): if request.command != 'GET': request.error(400) # bad request return path, params, query, fragment = request.split_uri() if '%' in path: path = http_server.unquote(path) # strip off all leading slashes while path and path[0] == '/': path = path[1:] path, process_name_and_channel = path.split('/', 1) try: process_name, channel = process_name_and_channel.split('/', 1) except ValueError: # no channel specified, default channel to stdout process_name = process_name_and_channel channel = 'stdout' from supervisor.options import split_namespec group_name, process_name = split_namespec(process_name) group = self.supervisord.process_groups.get(group_name) if group is None: request.error(404) # not found return process = group.processes.get(process_name) if process is None: request.error(404) # not found return logfile = getattr(process.config, '%s_logfile' % channel, None) if logfile is None or not os.path.exists(logfile): # XXX problematic: processes that don't start won't have a log # file and we probably don't want to go into fatal state if we try # to read the log of a process that did not start. request.error(410) # gone return mtime = os.stat(logfile)[stat.ST_MTIME] request['Last-Modified'] = http_date.build_http_date(mtime) request['Content-Type'] = 'text/plain' # the lack of a Content-Length header makes the outputter # send a 'Transfer-Encoding: chunked' response request.push(tail_f_producer(request, logfile, 1024)) request.done()
def cgi_environment(self): env = {} # maps request some headers to environment variables. # (those that don't start with 'HTTP_') header2env = { 'content-length': 'CONTENT_LENGTH', 'content-type': 'CONTENT_TYPE', 'connection': 'CONNECTION_TYPE' } workdir = os.getcwd() (path, params, query, fragment) = self.split_uri() if params: path = path + params # undo medusa bug! while path and path[0] == '/': path = path[1:] if '%' in path: path = http_server.unquote(path) if query: query = query[1:] server = self.channel.server env['REQUEST_METHOD'] = self.command.upper() env['SERVER_PORT'] = str(server.port) env['SERVER_NAME'] = server.server_name env['SERVER_SOFTWARE'] = server.SERVER_IDENT env['SERVER_PROTOCOL'] = "HTTP/" + self.version env['channel.creation_time'] = self.channel.creation_time env['SCRIPT_NAME'] = '' env['PATH_INFO'] = '/' + path env['PATH_TRANSLATED'] = os.path.normpath(os.path.join( workdir, env['PATH_INFO'])) if query: env['QUERY_STRING'] = query env['GATEWAY_INTERFACE'] = 'CGI/1.1' if self.channel.addr: env['REMOTE_ADDR'] = self.channel.addr[0] else: env['REMOTE_ADDR'] = '127.0.0.1' for header in self.header: key, value = header.split(":", 1) key = key.lower() value = value.strip() if key in header2env and value: env[header2env.get(key)] = value else: key = 'HTTP_%s' % ("_".join(key.split("-"))).upper() if value and key not in env: env[key] = value return env
def handle_request(self, request): if request.command != 'GET': request.error (400) # bad request return path, params, query, fragment = request.split_uri() if '%' in path: path = http_server.unquote(path) # strip off all leading slashes while path and path[0] == '/': path = path[1:] path, process_name_and_channel = path.split('/', 1) try: process_name, channel = process_name_and_channel.split('/', 1) except ValueError: # no channel specified, default channel to stdout process_name = process_name_and_channel channel = 'stdout' from supervisor.options import split_namespec group_name, process_name = split_namespec(process_name) group = self.supervisord.process_groups.get(group_name) if group is None: request.error(404) # not found return process = group.processes.get(process_name) if process is None: request.error(404) # not found return logfile = getattr(process.config, '%s_logfile' % channel, None) if logfile is None or not os.path.exists(logfile): # XXX problematic: processes that don't start won't have a log # file and we probably don't want to go into fatal state if we try # to read the log of a process that did not start. request.error(410) # gone return mtime = os.stat(logfile)[stat.ST_MTIME] request['Last-Modified'] = http_date.build_http_date(mtime) request['Content-Type'] = 'text/plain' # the lack of a Content-Length header makes the outputter # send a 'Transfer-Encoding: chunked' response request.push(tail_f_producer(request, logfile, 1024)) request.done()
def cgi_environment(self): env = {} # maps request some headers to environment variables. # (those that don't start with 'HTTP_') header2env= {'content-length' : 'CONTENT_LENGTH', 'content-type' : 'CONTENT_TYPE', 'connection' : 'CONNECTION_TYPE'} workdir = os.getcwd() (path, params, query, fragment) = self.split_uri() if params: path = path + params # undo medusa bug! while path and path[0] == '/': path = path[1:] if '%' in path: path = http_server.unquote(path) if query: query = query[1:] server = self.channel.server env['REQUEST_METHOD'] = self.command.upper() env['SERVER_PORT'] = str(server.port) env['SERVER_NAME'] = server.server_name env['SERVER_SOFTWARE'] = server.SERVER_IDENT env['SERVER_PROTOCOL'] = "HTTP/" + self.version env['channel.creation_time'] = self.channel.creation_time env['SCRIPT_NAME'] = '' env['PATH_INFO'] = '/' + path env['PATH_TRANSLATED'] = os.path.normpath(os.path.join( workdir, env['PATH_INFO'])) if query: env['QUERY_STRING'] = query env['GATEWAY_INTERFACE'] = 'CGI/1.1' if self.channel.addr: env['REMOTE_ADDR'] = self.channel.addr[0] else: env['REMOTE_ADDR'] = '127.0.0.1' for header in self.header: key,value=header.split(":",1) key=key.lower() value=value.strip() if header2env.has_key(key) and value: env[header2env.get(key)]=value else: key='HTTP_%s' % ("_".join(key.split( "-"))).upper() if value and not env.has_key(key): env[key]=value return env
def found_terminator (self): """ We only override this to use 'deferring_http_request' class instead of the normal http_request class; it sucks to need to override this """ if self.current_request: self.current_request.found_terminator() else: header = self.in_buffer self.in_buffer = '' lines = header.split('\r\n') # -------------------------------------------------- # crack the request header # -------------------------------------------------- while lines and not lines[0]: # as per the suggestion of http-1.1 section 4.1, (and # Eric Parker <*****@*****.**>), ignore a leading # blank lines (buggy browsers tack it onto the end of # POST requests) lines = lines[1:] if not lines: self.close_when_done() return request = lines[0] command, uri, version = http_server.crack_request (request) header = http_server.join_headers (lines[1:]) # unquote path if necessary (thanks to Skip Montanaro for pointing # out that we must unquote in piecemeal fashion). rpath, rquery = http_server.splitquery(uri) if '%' in rpath: if rquery: uri = http_server.unquote (rpath) + '?' + rquery else: uri = http_server.unquote (rpath) r = deferring_http_request (self, request, command, uri, version, header) self.request_counter.increment() self.server.total_requests.increment() if command is None: self.log_info ('Bad HTTP request: %s' % repr(request), 'error') r.error (400) return # -------------------------------------------------- # handler selection and dispatch # -------------------------------------------------- for h in self.server.handlers: if h.match (r): try: self.current_request = r # This isn't used anywhere. # r.handler = h # CYCLE h.handle_request (r) except: self.server.exceptions.increment() (file, fun, line), t, v, tbinfo = \ asyncore.compact_traceback() self.server.log_info( 'Server Error: %s, %s: file: %s line: %s' % (t,v,file,line), 'error') try: r.error (500) except: pass return # no handlers, so complain r.error (404)
def found_terminator(self): """ We only override this to use 'deferring_http_request' class instead of the normal http_request class; it sucks to need to override this """ if self.current_request: self.current_request.found_terminator() else: # we convert the header to text to facilitate processing. # some of the underlying APIs (such as splitquery) # expect text rather than bytes. header = as_string(self.in_buffer) self.in_buffer = b'' lines = header.split('\r\n') # -------------------------------------------------- # crack the request header # -------------------------------------------------- while lines and not lines[0]: # as per the suggestion of http-1.1 section 4.1, (and # Eric Parker <*****@*****.**>), ignore a leading # blank lines (buggy browsers tack it onto the end of # POST requests) lines = lines[1:] if not lines: self.close_when_done() return request = lines[0] command, uri, version = http_server.crack_request(request) header = http_server.join_headers(lines[1:]) # unquote path if necessary (thanks to Skip Montanaro for pointing # out that we must unquote in piecemeal fashion). rpath, rquery = http_server.splitquery(uri) if '%' in rpath: if rquery: uri = http_server.unquote(rpath) + '?' + rquery else: uri = http_server.unquote(rpath) r = deferring_http_request(self, request, command, uri, version, header) self.request_counter.increment() self.server.total_requests.increment() if command is None: self.log_info('Bad HTTP request: %s' % repr(request), 'error') r.error(400) return # -------------------------------------------------- # handler selection and dispatch # -------------------------------------------------- for h in self.server.handlers: if h.match(r): try: self.current_request = r # This isn't used anywhere. # r.handler = h # CYCLE h.handle_request(r) except: self.server.exceptions.increment() (file, fun, line), t, v, tbinfo = \ asyncore.compact_traceback() self.server.log_info( 'Server Error: %s, %s: file: %s line: %s' % (t, v, file, line), 'error') try: r.error(500) except: pass return # no handlers, so complain r.error(404)