Beispiel #1
0
    def serve_client(self, client, req: Request):
        try:
            Logger.debug_info(f'Request {req}')
            if req.insufficient():
                raise Errors.MALFORMED_REQ

            a = time.perf_counter()
            res = self.handle_req(req)
            Logger.debug_info(
                f'Request handling time {time.perf_counter() - a}')
            Logger.debug_info(f'Response prepared {res}')

            Response.send_response(client, res)
            Logger.debug_info(f'Response sent')

            Logger.info(f'Source Requested',
                        extra={
                            'method': req.method,
                            'url': req.path,
                            'code': res.status,
                            'ip': client.getpeername()
                        })

            if req.headers.get('Connection') == 'keep-alive':
                client.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            if req.headers.get('Connection') == 'close':
                self.close(client)
        except KeepAliveExpire:
            self.close(client)
        except Exception as e:
            Logger.exception(f'Client handling failed')
            send_error(client, e, self.configurator)
Beispiel #2
0
    def test_guest_book_post(self):
        req_line = (
            b'POST /post HTTP/1.1\r\n'
            b'Host: 0.0.0.0:8000\r\n'
            b'Content-Type: application/x-www-form-urlencoded\r\n'
            b'Accept-Encoding: gzip, deflate\r\n'
            b'Upgrade-Insecure-Requests: 1\r\n'
            b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,'
            b'*/*;q=0.8\r\n'
            b'Content-Length: 17\r\n'
            b'Accept-Language: en-us\r\n'
            b'\r\n'
            b'username=a&post=b')
        server = self.make_server()
        req = Request.fill_from_line(req_line)
        res: Response = server.handle_req(req)

        self.assertEqual(res.body,
                         b"POST ADDED {'username': ['a'], 'post': ['b']}")

        res = self.guest_book_get(server)

        self.assertEqual(json.loads(res.body), [{
            "username": "******",
            "post": "Post"
        }, {
            'post': ['b'],
            'username': ['a']
        }])
Beispiel #3
0
    def test_get_res(self):
        line = (b'GET / HTTP/1.1\r\n'
                b'Host: 0.0.0.0:8000\r\n'
                b'Accept: */*\r\n\r\n')

        server = self.make_server()
        req = Request()
        split = Request.split_keep_sep(line, b'\r\n')

        for s in split:
            if req.dynamic_fill(s):
                res = server.handle_req(req)

                self.assertEqual(res.status, 200)
                self.assertEqual(res.reason, 'OK')
                headers_dict = dict(res.headers)
                self.assertTrue(headers_dict.get('Content-Type'))
                self.assertTrue(headers_dict.get('Content-Length'))
Beispiel #4
0
 def test_get_picture(self):
     req_line = b'GET /c.png HTTP/1.1\r\n' \
                b'Host: 0.0.0.0\r\n' \
                b'Accept: */*\r\n\r\n'
     server = self.make_server()
     req = Request.fill_from_line(req_line)
     res: Response = server.handle_req(req)
     with open(os.path.join(TEST_DATA_DIR, 'c.png'), 'rb') as pic:
         self.assertEqual(res.body, pic.read())
Beispiel #5
0
    def guest_book_get(self, server):
        req_line = (b'GET /posts HTTP/1.1\r\n'
                    b'Host: 0.0.0.0:8000\r\n'
                    b'Accept: */*\r\n'
                    b'Accept-Language: en-us\r\n'
                    b'Accept-Encoding: gzip, deflate\r\n'
                    b'\r\n')

        req = Request.fill_from_line(req_line)
        return server.handle_req(req)
Beispiel #6
0
def save(req: Request, server):
    h = re.compile(
        b'-+?.+?\r\n'
        b'Content-Disposition: form-data; '
        b'name=\"(?P<name>.*?)\"; '
        b'filename=\"(?P<filename>.*?)\"\r\n'
        b'.+?: (?P<ct>.+?)\r\n'
        b'\r\n', re.S)

    tail_pos = 3
    while True:
        req.body_file.seek(-tail_pos, 2)
        tail = req.body_file.tell()
        t = req.body_file.read(tail_pos)
        if t.startswith(b'\r\n'):
            break
        tail_pos += 1

    head_crlf_count = 4
    head = b''

    req.body_file.seek(0)
    i = 0
    while True:
        if i == head_crlf_count:
            break
        head += req.body_file.read(1)
        if head.endswith(b'\r\n'):
            i += 1

    data_start = req.body_file.tell()

    match = h.search(head)
    if not match:
        raise Errors.MALFORMED_REQ
    groups = match.groupdict()
    ftype = groups.get('name')
    fname = Request.decode(groups.get('filename'))
    if fname:
        with open(os.path.join(ROOT_DIR, 'tmp', 'saved', fname), 'wb') as f:
            f.write(req.body_file.read(tail - data_start))
        Logger.debug_info(f'{ftype} saved as {fname} ')

        body = f'{os.path.join(ROOT_DIR, "tmp", "saved")}' \
               f' - >' \
               f' {os.listdir(os.path.join(ROOT_DIR, "tmp", "saved"))}'
    else:
        body = 'Empty file'
    headers = [
        ('Content-Type', f'application/json'),
        ('Content-Disposition', f'inline; filename=Echo query'),
        ('Content-Length', len(body)),
        ('Location', '/upload'),
    ]
    return Response(301, 'Moved Permanently', headers, body.encode())
Beispiel #7
0
    def _accept(self, sock):
        (client, addr) = sock.accept()
        num = client.fileno()
        self.conns[num] = client
        self.requests[num] = Request()
        self.out_buff[num] = []
        Logger.debug_info(f'Connected {addr}')

        client.setblocking(False)
        self.poller.register(client, selectors.EVENT_READ, self._read)
        Logger.debug_info(f'EVENT_READ Registered {addr}')
Beispiel #8
0
    def _read(self, client):
        try:
            line: bytes = client.recv(self.MAX_LINE)
            if not line:
                self.poller.unregister(client)
                del self.conns[client.fileno()]
                return
            num = client.fileno()
            req_builder: Request = self.requests[num]
            split = Request.split_keep_sep(line, bytes(os.linesep, 'utf-8'))

            for s in split:
                if req_builder.dynamic_fill(s):
                    self.requests[num] = Request()
                    # todo Request() change to req_builder
                    return self.serve_client(client, req_builder)
            print(req_builder)
        except Exception as e:
            Logger.exception('Read from client failed')
            send_error(client, e, self.configurator)
Beispiel #9
0
def handle_post(req: Request, server):
    req.body_file.seek(0)
    body = req.body_file.read()
    body = Request.decode(body)
    query = parse_qs(f'{body}')
    POSTS.append(query)
    body = f'POST ADDED {query}'.encode()
    headers = [
        ('Content-Type', f'application/json'),
        ('Content-Disposition', f'inline; filename=Post'),
        ('Content-Length', len(body)),
        ('Location', '/my_guest_book'),
    ]
    return Response(301, 'Moved Permanently', headers, body)
Beispiel #10
0
def post(req: Request, server):
    Logger.debug_info(f'POST---------')
    req.body_file.seek(0)
    body = req.body_file.read()
    body = Request.decode(body)
    Logger.debug_info(f'POSTED -> {body}')
    post_data = json.loads(body)
    BOOKS.append({
        'id': uuid.uuid4().hex,
        'title': post_data.get('title'),
        'author': post_data.get('author'),
        'read': post_data.get('read')
    })
    SUCCESS['message'] = 'Books added!'
    body = f'{json.dumps(SUCCESS)}'.encode()
    headers = [
        ('Content-Type', f'application/json'),
        ('Content-Disposition', f'inline; filename=Get posts'),
        ('Content-Length', len(body)),
        ("Access-Control-Allow-Origin", '*')
    ]
    return Response(200, 'OK', headers, body)