def parse_request_line(line, *, methods=ALLOWED_HTTP_METHODS): error_log.debug3('Parsing request line...') parts = line.split(b' ') if len(parts) != 3: raise ParserException(code='PARSER_BAD_REQUEST_LINE') method, request_target, http_version = parts method = method.decode('ascii') if method not in methods: raise ParserException(code='PARSER_UNKNOWN_METHOD') error_log.debug2('Parsed method %r', method) uri = parse_request_target(request_target) error_log.debug2('Parsed uri %r', uri) if not HTTP_VERSION_REGEX.match(http_version): raise ParserException(code='PARSER_BAD_HTTP_VERSION') http_version = http_version.decode('ascii') return ws.http.structs.HTTPRequestLine(method=method, request_target=uri, http_version=http_version)
def shutdown(self, how, pass_silently=False): error_log.debug2(SHUTDOWN_MSGS[how], super().fileno()) if pass_silently: try: super().shutdown(how) except OSError: pass else: super().shutdown(how)
def close(self, pass_silently=False): error_log.debug2('Closing socket %d', self.fileno()) if pass_silently: try: super().close() except OSError: error_log.exception('Closing socket %s failed.', self.fileno()) else: super().close()
def is_status_route(route): status_route = config.get('routes', 'status', fallback=None) if not status_route: error_log.debug2('Status route is not set.') return False status_route = ws.http.utils.normalized_route(status_route) route = ws.http.utils.normalized_route(route) return status_route == route
def is_static_route_depreciated(route): static_route = config.get('routes', 'static', fallback=None) if not static_route: error_log.debug2('Static route is not set.') return False static_route = ws.http.utils.normalized_route(static_route) route = ws.http.utils.normalized_route(route) return route.startswith(static_route)
def shutdown(self, how, pass_silently=False): error_log.debug2(SHUTDOWN_MSGS[how], super().fileno()) if pass_silently: try: super().shutdown(how) except OSError: error_log.exception('Shutting down socket %s failed.', self.fileno()) else: super().shutdown(how)
def get_file_depreciated(route): error_log.debug2('Serving static file.') resolved = resolve_route_depreciated(route, route_prefix=STATIC_ROUTE, dir_prefix=STATIC_DIR) if not resolved: return ws.http.utils.build_response(404) try: body_it = file_chunk_gen(resolved) # startup the generator to have exceptions blow here. next(body_it) return HTTPResponse( status_line=HTTPStatusLine(http_version='HTTP/1.1', status_code=200, reason_phrase=''), headers=HTTPHeaders({ 'Content-Length': os.path.getsize(resolved) }), body=body_it ) except (FileNotFoundError, IsADirectoryError): return ws.http.utils.build_response(404)
def parse(sock): lines, leftover_body = recv_request(sock) try: request_line = parse_request_line(lines[0]) error_log.debug2('Parsed request line %s', request_line) headers = parse_headers(lines[1:]) except UnicodeDecodeError as err: raise ParserException(code='BAD_ENCODING') from err error_log.debug2('headers is %r with type %r', headers, type(headers)) error_log.debug2('Deferring parsing of body to later.') request = ws.http.structs.HTTPRequest(request_line=request_line, headers=headers) return request, leftover_body
def status_depreciated(): error_log.debug2('Serving status page.') # for pos, part in enumerate(config['access_log']['format'].split()): # match = FORMAT_FIELD_REGEX.match(part) # if match: # field = match.group(1) # fields_format[pos + offset] = field # if field == 'asctime': # offset += 1 # elif field == 'request_line': # offset += 2 stats = {} fields = { 7: 'ru_utime', 8: 'ru_stime', 9: 'ru_maxrss', 10: 'response_time', 11: 'parse_time', 12: 'total_time' } line_count = -1 with open(config['access_log']['file_name'], mode='r') as f: for line_count, line in enumerate(f): for pos, part in enumerate(line.split()): if pos not in fields: continue fn = fields[pos] avg = 'avg_{}'.format(fn) max_ = 'max_{}'.format(fn) try: val = float(part) except ValueError: continue if avg not in stats: stats[avg] = {'val': 0, 'count': 0} stats[avg]['val'] += val stats[avg]['count'] += 1 stats[max_] = max(val, stats.get(max_, 0)) lines = [] for stat, entry in stats.items(): if stat.startswith('max_'): val = entry else: val = entry['val'] / entry['count'] lines.append('{stat}={val}'.format(stat=stat, val=val)) lines.append('served_requests={}\n'.format(line_count + 1)) lines.sort(key=lambda s: s.strip('max').strip('avg')) body = b'\n'.join(l.encode('ascii') for l in lines) # TODO fix these shenanigans ib = io.BytesIO() ib.write(body) ib.seek(0) return ws.http.utils.build_response( 200, body=ib, headers={'Content-Length': len(body), 'Content-Type': 'text/html'} )