gproxy_protocol/transform/openai/websocket/to_http/
request.rs1use crate::openai::create_response::request::{OpenAiCreateResponseRequest, RequestBody};
2use crate::openai::create_response::types::Metadata;
3use crate::openai::create_response::websocket::request::OpenAiCreateResponseWebSocketConnectRequest;
4use crate::openai::create_response::websocket::types::OpenAiCreateResponseWebSocketClientMessage;
5use crate::transform::openai::websocket::context::OpenAiWebsocketTransformContext;
6use crate::transform::openai::websocket::from_http::request::OPENAI_CLIENT_METADATA_TUNNEL_PREFIX;
7use crate::transform::utils::TransformError;
8
9fn inject_client_metadata_into_request_body(
10 body: &mut RequestBody,
11 client_metadata: Option<&Metadata>,
12 ctx: &mut OpenAiWebsocketTransformContext,
13) {
14 let Some(client_metadata) = client_metadata else {
15 return;
16 };
17 if client_metadata.is_empty() {
18 return;
19 }
20
21 let metadata = body.metadata.get_or_insert_with(Metadata::new);
22 for (key, value) in client_metadata {
23 let tunnel_key = format!("{OPENAI_CLIENT_METADATA_TUNNEL_PREFIX}{key}");
24 if metadata.contains_key(&tunnel_key) {
25 ctx.push_warning(format!(
26 "openai websocket to_http request: metadata tunnel key conflict overwritten `{tunnel_key}`"
27 ));
28 }
29 metadata.insert(tunnel_key, value.clone());
30 }
31 ctx.push_warning(
32 "openai websocket to_http request: client_metadata tunneled through metadata".to_string(),
33 );
34}
35
36pub fn websocket_client_message_to_openai_request_with_context(
37 value: &OpenAiCreateResponseWebSocketClientMessage,
38) -> Result<(OpenAiCreateResponseRequest, OpenAiWebsocketTransformContext), TransformError> {
39 let mut ctx = OpenAiWebsocketTransformContext::default();
40
41 let request = match value {
42 OpenAiCreateResponseWebSocketClientMessage::ResponseCreate(payload) => {
43 let mut body = payload.request.clone();
44 inject_client_metadata_into_request_body(
45 &mut body,
46 payload.client_metadata.as_ref(),
47 &mut ctx,
48 );
49 if payload.generate == Some(false) {
50 ctx.push_warning(
51 "openai websocket to_http request: dropped generate=false flag".to_string(),
52 );
53 }
54 OpenAiCreateResponseRequest {
55 body,
56 ..OpenAiCreateResponseRequest::default()
57 }
58 }
59 OpenAiCreateResponseWebSocketClientMessage::ResponseAppend(payload) => {
60 let mut body = RequestBody {
61 input: Some(payload.input.clone()),
62 stream: Some(true),
63 ..RequestBody::default()
64 };
65 inject_client_metadata_into_request_body(
66 &mut body,
67 payload.client_metadata.as_ref(),
68 &mut ctx,
69 );
70 OpenAiCreateResponseRequest {
71 body,
72 ..OpenAiCreateResponseRequest::default()
73 }
74 }
75 };
76
77 Ok((request, ctx))
78}
79
80pub fn websocket_connect_to_openai_request_with_context(
81 value: &OpenAiCreateResponseWebSocketConnectRequest,
82) -> Result<(OpenAiCreateResponseRequest, OpenAiWebsocketTransformContext), TransformError> {
83 let Some(message) = value.body.as_ref() else {
84 let mut ctx = OpenAiWebsocketTransformContext::default();
85 ctx.push_warning(
86 "openai websocket to_http request: missing initial body, downgraded to empty request"
87 .to_string(),
88 );
89 return Ok((OpenAiCreateResponseRequest::default(), ctx));
90 };
91 websocket_client_message_to_openai_request_with_context(message)
92}
93
94impl TryFrom<&OpenAiCreateResponseWebSocketClientMessage> for OpenAiCreateResponseRequest {
95 type Error = TransformError;
96
97 fn try_from(
98 value: &OpenAiCreateResponseWebSocketClientMessage,
99 ) -> Result<Self, TransformError> {
100 Ok(websocket_client_message_to_openai_request_with_context(value)?.0)
101 }
102}
103
104impl TryFrom<&OpenAiCreateResponseWebSocketConnectRequest> for OpenAiCreateResponseRequest {
105 type Error = TransformError;
106
107 fn try_from(
108 value: &OpenAiCreateResponseWebSocketConnectRequest,
109 ) -> Result<Self, TransformError> {
110 Ok(websocket_connect_to_openai_request_with_context(value)?.0)
111 }
112}
113
114impl TryFrom<OpenAiCreateResponseWebSocketConnectRequest> for OpenAiCreateResponseRequest {
115 type Error = TransformError;
116
117 fn try_from(
118 value: OpenAiCreateResponseWebSocketConnectRequest,
119 ) -> Result<Self, TransformError> {
120 OpenAiCreateResponseRequest::try_from(&value)
121 }
122}