|
1 | 1 | import asyncio
|
| 2 | +import contextlib |
| 3 | +import datetime |
| 4 | +import os |
2 | 5 | import re
|
3 | 6 | import ssl
|
| 7 | +import tempfile |
4 | 8 | from dataclasses import dataclass
|
5 | 9 | from typing import Dict, List, Optional, Tuple, Union
|
6 | 10 | from urllib.parse import unquote, urljoin, urlparse
|
|
26 | 30 | setup_logging()
|
27 | 31 | logger = structlog.get_logger("codegate").bind(origin="copilot_proxy")
|
28 | 32 |
|
| 33 | + |
| 34 | +TEMPDIR = None |
| 35 | +if os.getenv("CODEGATE_DUMP_DIR"): |
| 36 | + basedir = os.getenv("CODEGATE_DUMP_DIR") |
| 37 | + TEMPDIR = tempfile.TemporaryDirectory(prefix="codegate-", dir=basedir, delete=False) |
| 38 | + |
| 39 | + |
| 40 | +def _dump_data(suffix, func): |
| 41 | + if os.getenv("CODEGATE_DUMP_DIR"): |
| 42 | + buf = bytearray(b"") |
| 43 | + |
| 44 | + def inner(self, data: bytes): |
| 45 | + nonlocal buf |
| 46 | + func(self, data) |
| 47 | + buf.extend(data) |
| 48 | + |
| 49 | + if data == b"0\r\n\r\n": |
| 50 | + ts = datetime.datetime.now() |
| 51 | + fname = os.path.join(TEMPDIR.name, ts.strftime(f"{suffix}-%Y%m%dT%H%M%S%f.txt")) |
| 52 | + with open(fname, mode="wb") as fd: |
| 53 | + fd.write(buf) |
| 54 | + buf = bytearray() |
| 55 | + |
| 56 | + return inner |
| 57 | + return func |
| 58 | + |
| 59 | + |
| 60 | +def _dump_request(func): |
| 61 | + return _dump_data("request", func) |
| 62 | + |
| 63 | + |
| 64 | +def _dump_response(func): |
| 65 | + return _dump_data("response", func) |
| 66 | + |
| 67 | + |
29 | 68 | # Constants
|
30 | 69 | MAX_BUFFER_SIZE = 10 * 1024 * 1024 # 10MB
|
31 | 70 | CHUNK_SIZE = 64 * 1024 # 64KB
|
@@ -914,6 +953,7 @@ def _process_chunk(self, chunk: bytes):
|
914 | 953 |
|
915 | 954 | self.stream_queue.put_nowait(record)
|
916 | 955 |
|
| 956 | + @_dump_response |
917 | 957 | def _proxy_transport_write(self, data: bytes):
|
918 | 958 | # For debugging only
|
919 | 959 | # self.data_sent.append(data)
|
|
0 commit comments