diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2024-03-11 18:59:53 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2024-03-11 18:59:53 +0000 |
commit | 9b78be4f03b67d4feca3081b9427ac5ed1d241c9 (patch) | |
tree | ab6bb423640ace63bbfa71de24a167fbfd2d7dc5 /src/libserver | |
parent | a4de9b2ebb9aa47ebff0c71fb980daf4eb5ca0cc (diff) | |
download | rspamd-9b78be4f03b67d4feca3081b9427ac5ed1d241c9.tar.gz rspamd-9b78be4f03b67d4feca3081b9427ac5ed1d241c9.zip |
[Feature] Support reply in message pack format
Rspamd currently sends reply in JSON format. However, message pack seems to
be a better choice for a compatible client. It is faster and does not need
escaping or even UTF8 validation. This is a surface for further updates.
Diffstat (limited to 'src/libserver')
-rw-r--r-- | src/libserver/protocol.c | 22 | ||||
-rw-r--r-- | src/libserver/protocol.h | 19 |
2 files changed, 34 insertions, 7 deletions
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index 37a41c111..5993da61e 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -1636,7 +1636,7 @@ rspamd_protocol_write_ucl(struct rspamd_task *task, } void rspamd_protocol_http_reply(struct rspamd_http_message *msg, - struct rspamd_task *task, ucl_object_t **pobj) + struct rspamd_task *task, ucl_object_t **pobj, int how) { struct rspamd_scan_result *metric_res; const struct rspamd_re_cache_stat *restat; @@ -1695,7 +1695,7 @@ void rspamd_protocol_http_reply(struct rspamd_http_message *msg, if (msg->method < HTTP_SYMBOLS && !RSPAMD_TASK_IS_SPAMC(task)) { msg_debug_protocol("writing json reply"); - rspamd_ucl_emit_fstring(top, UCL_EMIT_JSON_COMPACT, &reply); + rspamd_ucl_emit_fstring(top, how, &reply); } else { if (RSPAMD_TASK_IS_SPAMC(task)) { @@ -2111,6 +2111,16 @@ void rspamd_protocol_write_reply(struct rspamd_task *task, ev_tstamp timeout) MESSAGE_FIELD_CHECK(task, message_id)); } + const rspamd_ftok_t *accept_hdr; + int out_type = UCL_EMIT_JSON_COMPACT; + accept_hdr = rspamd_task_get_request_header(task, "Accept"); + + if (accept_hdr && rspamd_substring_search(accept_hdr->begin, accept_hdr->len, + "application/msgpack", sizeof("application/msgpack") - 1)) { + ctype = "application/msgpack"; + out_type = UCL_EMIT_MSGPACK; + } + /* Compatibility */ if (task->cmd == CMD_CHECK_RSPAMC) { msg->method = HTTP_SYMBOLS; @@ -2134,15 +2144,15 @@ void rspamd_protocol_write_reply(struct rspamd_task *task, ev_tstamp timeout) ucl_object_fromstring(g_quark_to_string(task->err->domain)), "error_domain", 0, false); reply = rspamd_fstring_sized_new(256); - rspamd_ucl_emit_fstring(top, UCL_EMIT_JSON_COMPACT, &reply); + rspamd_ucl_emit_fstring(top, out_type, &reply); ucl_object_unref(top); /* We also need to validate utf8 */ - if (rspamd_fast_utf8_validate(reply->str, reply->len) != 0) { + if (out_type != UCL_EMIT_MSGPACK && rspamd_fast_utf8_validate(reply->str, reply->len) != 0) { gsize valid_len; gchar *validated; - /* We copy reply several times here but it should be a rare case */ + /* We copy reply several times here, but it should be a rare case */ validated = rspamd_str_make_utf_valid(reply->str, reply->len, &valid_len, task->task_pool); rspamd_http_message_set_body(msg, validated, valid_len); @@ -2161,7 +2171,7 @@ void rspamd_protocol_write_reply(struct rspamd_task *task, ev_tstamp timeout) case CMD_CHECK_SPAMC: case CMD_SKIP: case CMD_CHECK_V2: - rspamd_protocol_http_reply(msg, task, NULL); + rspamd_protocol_http_reply(msg, task, NULL, out_type); rspamd_protocol_write_log_pipe(task); break; case CMD_PING: diff --git a/src/libserver/protocol.h b/src/libserver/protocol.h index 0e3c18744..38d9cef4b 100644 --- a/src/libserver/protocol.h +++ b/src/libserver/protocol.h @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Vsevolod Stakhov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** * @file protocol.h * Rspamd protocol definition @@ -70,7 +86,8 @@ gboolean rspamd_protocol_handle_request(struct rspamd_task *task, * @param task */ void rspamd_protocol_http_reply(struct rspamd_http_message *msg, - struct rspamd_task *task, ucl_object_t **pobj); + struct rspamd_task *task, ucl_object_t **pobj, + int how); /** * Write data to log pipes |