1919
2020#include <fluent-bit/flb_output_plugin.h>
2121#include <fluent-bit/flb_http_server.h>
22+ #include <fluent-bit/flb_gzip.h>
23+ #include <monkey/mk_http_parser.h>
24+ #include <string.h>
2225#include "prom.h"
2326#include "prom_http.h"
2427
@@ -157,10 +160,73 @@ static int http_server_mq_create(struct prom_http *ph)
157160 return 0 ;
158161}
159162
163+ /* Check if client accepts gzip encoding */
164+ static int client_accepts_gzip (mk_request_t * request )
165+ {
166+ struct mk_http_header * header ;
167+ const char * accept_encoding ;
168+ size_t len ;
169+ const char * p ;
170+ const char * end ;
171+
172+ /* Get Accept-Encoding header */
173+ header = mk_http_header_get (MK_HEADER_ACCEPT_ENCODING , request , NULL , 0 );
174+ if (!header || header -> val .len == 0 ) {
175+ return 0 ;
176+ }
177+
178+ accept_encoding = header -> val .data ;
179+ len = header -> val .len ;
180+
181+ /* Check if "gzip" is present in Accept-Encoding header (case-insensitive) */
182+ if (len < 4 ) {
183+ return 0 ;
184+ }
185+
186+ p = accept_encoding ;
187+ end = accept_encoding + len ;
188+
189+ /* Search for "gzip" token */
190+ while (p < end - 3 ) {
191+ /* Case-insensitive comparison for "gzip" */
192+ if ((p [0 ] == 'g' || p [0 ] == 'G' ) &&
193+ (p [1 ] == 'z' || p [1 ] == 'Z' ) &&
194+ (p [2 ] == 'i' || p [2 ] == 'I' ) &&
195+ (p [3 ] == 'p' || p [3 ] == 'P' )) {
196+ /* Check if it's a complete token (not part of another word) */
197+ /* Check character before "gzip" */
198+ if (p > accept_encoding ) {
199+ char prev = p [-1 ];
200+ if (prev != ',' && prev != ' ' && prev != '\t' ) {
201+ p ++ ;
202+ continue ;
203+ }
204+ }
205+ /* Check character after "gzip" */
206+ if (p + 4 < end ) {
207+ char next = p [4 ];
208+ if (next != ',' && next != ' ' && next != '\t' && next != ';' ) {
209+ p ++ ;
210+ continue ;
211+ }
212+ }
213+ /* Found valid "gzip" token */
214+ return 1 ;
215+ }
216+ p ++ ;
217+ }
218+
219+ return 0 ;
220+ }
221+
160222/* HTTP endpoint: /metrics */
161223static void cb_metrics (mk_request_t * request , void * data )
162224{
163225 struct prom_http_buf * buf ;
226+ void * compressed_data = NULL ;
227+ size_t compressed_size = 0 ;
228+ int use_gzip = 0 ;
229+ int ret ;
164230 (void ) data ;
165231
166232 buf = metrics_get_latest ();
@@ -172,9 +238,35 @@ static void cb_metrics(mk_request_t *request, void *data)
172238
173239 buf -> users ++ ;
174240
241+ /* Check if client accepts gzip encoding */
242+ use_gzip = client_accepts_gzip (request );
243+
244+ /* Compress data if client supports gzip */
245+ if (use_gzip ) {
246+ ret = flb_gzip_compress (buf -> buf_data , buf -> buf_size ,
247+ & compressed_data , & compressed_size );
248+ if (ret != 0 || !compressed_data ) {
249+ /* Compression failed, fall back to uncompressed */
250+ use_gzip = 0 ;
251+ if (compressed_data ) {
252+ flb_free (compressed_data );
253+ compressed_data = NULL ;
254+ }
255+ }
256+ }
257+
175258 mk_http_status (request , 200 );
176259 flb_hs_add_content_type_to_req (request , FLB_HS_CONTENT_TYPE_PROMETHEUS );
177- mk_http_send (request , buf -> buf_data , buf -> buf_size , NULL );
260+
261+ /* Add Content-Encoding header if compressed */
262+ if (use_gzip && compressed_data ) {
263+ mk_http_header (request , "Content-Encoding" , 16 , "gzip" , 4 );
264+ mk_http_send (request , compressed_data , compressed_size , NULL );
265+ flb_free (compressed_data );
266+ } else {
267+ mk_http_send (request , buf -> buf_data , buf -> buf_size , NULL );
268+ }
269+
178270 mk_http_done (request );
179271
180272 buf -> users -- ;
0 commit comments