This commit is contained in:
Christian Grothoff 2017-04-17 01:29:36 +02:00
parent 0b3abbd304
commit 5a321621f4
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
5 changed files with 176 additions and 6 deletions

View File

@ -1,3 +1,6 @@
Mon Apr 17 01:29:07 CEST 2017
Add support for HTTP body compression (#4982). -CG
Mon Mar 20 04:37:46 CET 2017
Implemented first working version of taler-auditor. -CG

View File

@ -55,6 +55,7 @@ taler_exchange_httpd_LDADD = \
-lgnunetutil \
-lgnunetjson \
-ljansson \
-lz \
-lpthread
if HAVE_DEVELOPER

View File

@ -71,6 +71,16 @@ struct TEH_KS_StateHandle
*/
char *keys_json;
/**
* deflate-compressed version of @e keys_json, or NULL if not available.
*/
void *keys_jsonz;
/**
* Number of bytes in @e keys_jsonz.
*/
size_t keys_jsonz_size;
/**
* Mapping from denomination keys to denomination key issue struct.
* Used to lookup the key by hash.
@ -709,6 +719,7 @@ ks_release_ (struct TEH_KS_StateHandle *key_state)
key_state->revoked_map = NULL;
}
GNUNET_free_non_null (key_state->keys_json);
GNUNET_free_non_null (key_state->keys_jsonz);
GNUNET_free (key_state);
}
}
@ -851,6 +862,17 @@ TEH_KS_acquire_ (const char *location)
JSON_INDENT (2));
GNUNET_assert (NULL != key_state->keys_json);
json_decref (keys);
/* also compute compressed version of /keys */
key_state->keys_jsonz = GNUNET_strdup (key_state->keys_json);
key_state->keys_jsonz_size = strlen (key_state->keys_json);
if (MHD_YES !=
TEH_RESPONSE_body_compress (&key_state->keys_jsonz,
&key_state->keys_jsonz_size))
{
GNUNET_free (key_state->keys_jsonz);
key_state->keys_jsonz = NULL;
key_state->keys_jsonz_size = 0;
}
internal_key_state = key_state;
}
key_state = internal_key_state;
@ -1225,10 +1247,26 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
struct MHD_Response *response;
int ret;
char dat[128];
char *json;
size_t json_len;
int comp;
key_state = TEH_KS_acquire ();
response = MHD_create_response_from_buffer (strlen (key_state->keys_json),
key_state->keys_json,
comp = MHD_NO;
if (NULL != key_state->keys_jsonz)
comp = TEH_RESPONSE_can_compress (connection);
if (MHD_YES == comp)
{
json = key_state->keys_jsonz;
json_len = key_state->keys_jsonz_size;
}
else
{
json = key_state->keys_json;
json_len = strlen (key_state->keys_json);
}
response = MHD_create_response_from_buffer (json_len,
json,
MHD_RESPMEM_MUST_COPY);
TEH_KS_release (key_state);
if (NULL == response)
@ -1241,6 +1279,15 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
MHD_add_response_header (response,
MHD_HTTP_HEADER_CONTENT_TYPE,
rh->mime_type));
if (MHD_YES !=
MHD_add_response_header (response,
MHD_HTTP_HEADER_CONTENT_ENCODING,
"deflate"))
{
GNUNET_break (0);
MHD_destroy_response (response);
return MHD_NO;
}
get_date_string (key_state->reload_time,
dat);
GNUNET_break (MHD_YES ==

View File

@ -23,6 +23,7 @@
* @author Christian Grothoff
*/
#include "platform.h"
#include <zlib.h>
#include "taler-exchange-httpd_responses.h"
#include "taler_util.h"
#include "taler_json_lib.h"
@ -47,6 +48,74 @@ TEH_RESPONSE_add_global_headers (struct MHD_Response *response)
}
/**
* Is HTTP body deflate compression supported by the client?
*
* @param connection connection to check
* @return #MHD_YES if 'deflate' compression is allowed
*/
int
TEH_RESPONSE_can_compress (struct MHD_Connection *connection)
{
const char *ae;
const char *de;
ae = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_ACCEPT_ENCODING);
if (NULL == ae)
return MHD_NO;
de = strstr (ae,
"deflate");
if (NULL == de)
return MHD_NO;
if ( ( (de == ae) ||
( de[-1] == ',') ||
(de[-1] == ' ') ) &&
( (de[strlen ("deflate")] == '\0') ||
(de[strlen ("deflate")] == ',') ) )
return MHD_YES;
return MHD_NO;
}
/**
* Try to compress a response body. Updates @a buf and @buf_size.
*
* @param[in,out] buf pointer to body to compress
* @param[in,out] buf_size pointer to initial size of @a buf
* @return #MHD_TES if @a buf was compressed
*/
int
TEH_RESPONSE_body_compress (void **buf,
size_t *buf_size)
{
Bytef *cbuf;
uLongf cbuf_size;
int ret;
cbuf_size = compressBound (*buf_size);
cbuf = malloc (cbuf_size);
if (NULL == cbuf)
return MHD_NO;
ret = compress (cbuf,
&cbuf_size,
(const Bytef *) *buf,
*buf_size);
if ( (Z_OK != ret) ||
(cbuf_size >= *buf_size) )
{
/* compression failed */
free (cbuf);
return MHD_NO;
}
free (*buf);
*buf = (void *) cbuf;
*buf_size = (size_t) cbuf_size;
return MHD_YES;
}
/**
* Send JSON object as response.
*
@ -61,12 +130,26 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
unsigned int response_code)
{
struct MHD_Response *resp;
char *json_str;
void *json_str;
size_t json_len;
int ret;
int comp;
json_str = json_dumps (json, JSON_INDENT(2));
GNUNET_assert (NULL != json_str);
resp = MHD_create_response_from_buffer (strlen (json_str),
json_str = json_dumps (json,
JSON_INDENT(2));
if (NULL == json_str)
{
GNUNET_break (0);
return MHD_NO;
}
json_len = strlen (json_str);
/* try to compress the body */
comp = MHD_NO;
if (MHD_YES ==
TEH_RESPONSE_can_compress (connection))
comp = TEH_RESPONSE_body_compress (&json_str,
&json_len);
resp = MHD_create_response_from_buffer (json_len,
json_str,
MHD_RESPMEM_MUST_FREE);
if (NULL == resp)
@ -79,6 +162,19 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
(void) MHD_add_response_header (resp,
MHD_HTTP_HEADER_CONTENT_TYPE,
"application/json");
if (MHD_YES == comp)
{
/* Need to indicate to client that body is compressed */
if (MHD_NO ==
MHD_add_response_header (resp,
MHD_HTTP_HEADER_CONTENT_ENCODING,
"deflate"))
{
GNUNET_break (0);
MHD_destroy_response (resp);
return MHD_NO;
}
}
ret = MHD_queue_response (connection,
response_code,
resp);

View File

@ -33,6 +33,7 @@
#include "taler-exchange-httpd.h"
#include "taler-exchange-httpd_db.h"
/**
* Add headers we want to return in every response.
* Useful for testing, like if we want to always close
@ -44,6 +45,28 @@ void
TEH_RESPONSE_add_global_headers (struct MHD_Response *response);
/**
* Try to compress a response body. Updates @a buf and @buf_size.
*
* @param[in,out] buf pointer to body to compress
* @param[in,out] buf_size pointer to initial size of @a buf
* @return #MHD_TES if @a buf was compressed
*/
int
TEH_RESPONSE_body_compress (void **buf,
size_t *buf_size);
/**
* Is HTTP body deflate compression supported by the client?
*
* @param connection connection to check
* @return #MHD_YES if 'deflate' compression is allowed
*/
int
TEH_RESPONSE_can_compress (struct MHD_Connection *connection);
/**
* Send JSON object as response.
*