/office/* 反向代理到本机 univer-office Node 服务(9091),承接 markdown<->IDocumentData 转换 + docx/xlsx/ppt 导出。含 office_proxy.py + config.json 路由 + pipeline_app 注册 + restart-pipeline.sh
52 lines
2.1 KiB
Python
52 lines
2.1 KiB
Python
"""office_proxy - 把 /office/* 请求转发到本机 univer-office Node 服务(9091)。
|
||
|
||
univer-office 承担 markdown<->IDocumentData 转换与 docx/xlsx/ppt 导出,
|
||
这些能力是 Node 生态(Univer + docx/exceljs/pptxgenjs),Python 侧无法直接实现,
|
||
故通过 ahserver 的 startswiths 机制做反向代理。
|
||
|
||
路由映射:
|
||
/office/render -> http://127.0.0.1:9091/render (markdown -> IDocumentData)
|
||
/office/extract -> http://127.0.0.1:9091/extract (IDocumentData -> 纯文本)
|
||
/office/export/docx -> http://127.0.0.1:9091/export/docx (markdown -> docx 二进制)
|
||
"""
|
||
import aiohttp
|
||
from aiohttp import web
|
||
from appPublic.registerfunction import registerFunction
|
||
from appPublic.log import error, debug
|
||
|
||
OFFICE_BACKEND = 'http://127.0.0.1:9091'
|
||
|
||
# hop-by-hop 头,转发时需剔除
|
||
_HOP_BY_HOP = {
|
||
'host', 'content-length', 'transfer-encoding', 'connection',
|
||
'keep-alive', 'upgrade', 'proxy-authenticate', 'proxy-authorization',
|
||
'te', 'trailers',
|
||
}
|
||
|
||
|
||
async def office_proxy(request, params_kw, *args, **env):
|
||
"""把 /office/* 转发到 9091。args = leading 之后的路径段,如 ('render',) 或 ('export','docx')。"""
|
||
path = '/'.join(args)
|
||
url = f'{OFFICE_BACKEND}/{path}'
|
||
debug(f'office_proxy: {request.method} {url}')
|
||
|
||
body = await request.read()
|
||
headers = {k: v for k, v in request.headers.items() if k.lower() not in _HOP_BY_HOP}
|
||
|
||
try:
|
||
timeout = aiohttp.ClientTimeout(total=180)
|
||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||
async with session.request(request.method, url, headers=headers, data=body) as resp:
|
||
resp_body = await resp.read()
|
||
resp_headers = {
|
||
k: v for k, v in resp.headers.items()
|
||
if k.lower() not in _HOP_BY_HOP and k.lower() != 'content-encoding'
|
||
}
|
||
return web.Response(body=resp_body, status=resp.status, headers=resp_headers)
|
||
except Exception as e:
|
||
error(f'office_proxy failed: {e}')
|
||
return web.Response(body=f'office backend error: {e}'.encode(), status=502)
|
||
|
||
|
||
registerFunction('office_proxy', office_proxy)
|