implement #4982
This commit is contained in:
parent
0b3abbd304
commit
5a321621f4
@ -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
|
Mon Mar 20 04:37:46 CET 2017
|
||||||
Implemented first working version of taler-auditor. -CG
|
Implemented first working version of taler-auditor. -CG
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ taler_exchange_httpd_LDADD = \
|
|||||||
-lgnunetutil \
|
-lgnunetutil \
|
||||||
-lgnunetjson \
|
-lgnunetjson \
|
||||||
-ljansson \
|
-ljansson \
|
||||||
|
-lz \
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
if HAVE_DEVELOPER
|
if HAVE_DEVELOPER
|
||||||
|
@ -71,6 +71,16 @@ struct TEH_KS_StateHandle
|
|||||||
*/
|
*/
|
||||||
char *keys_json;
|
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.
|
* Mapping from denomination keys to denomination key issue struct.
|
||||||
* Used to lookup the key by hash.
|
* Used to lookup the key by hash.
|
||||||
@ -709,6 +719,7 @@ ks_release_ (struct TEH_KS_StateHandle *key_state)
|
|||||||
key_state->revoked_map = NULL;
|
key_state->revoked_map = NULL;
|
||||||
}
|
}
|
||||||
GNUNET_free_non_null (key_state->keys_json);
|
GNUNET_free_non_null (key_state->keys_json);
|
||||||
|
GNUNET_free_non_null (key_state->keys_jsonz);
|
||||||
GNUNET_free (key_state);
|
GNUNET_free (key_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -851,6 +862,17 @@ TEH_KS_acquire_ (const char *location)
|
|||||||
JSON_INDENT (2));
|
JSON_INDENT (2));
|
||||||
GNUNET_assert (NULL != key_state->keys_json);
|
GNUNET_assert (NULL != key_state->keys_json);
|
||||||
json_decref (keys);
|
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;
|
internal_key_state = key_state;
|
||||||
}
|
}
|
||||||
key_state = internal_key_state;
|
key_state = internal_key_state;
|
||||||
@ -1225,10 +1247,26 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
|
|||||||
struct MHD_Response *response;
|
struct MHD_Response *response;
|
||||||
int ret;
|
int ret;
|
||||||
char dat[128];
|
char dat[128];
|
||||||
|
char *json;
|
||||||
|
size_t json_len;
|
||||||
|
int comp;
|
||||||
|
|
||||||
key_state = TEH_KS_acquire ();
|
key_state = TEH_KS_acquire ();
|
||||||
response = MHD_create_response_from_buffer (strlen (key_state->keys_json),
|
comp = MHD_NO;
|
||||||
key_state->keys_json,
|
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);
|
MHD_RESPMEM_MUST_COPY);
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
if (NULL == response)
|
if (NULL == response)
|
||||||
@ -1241,6 +1279,15 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
|
|||||||
MHD_add_response_header (response,
|
MHD_add_response_header (response,
|
||||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||||
rh->mime_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,
|
get_date_string (key_state->reload_time,
|
||||||
dat);
|
dat);
|
||||||
GNUNET_break (MHD_YES ==
|
GNUNET_break (MHD_YES ==
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
* @author Christian Grothoff
|
* @author Christian Grothoff
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include <zlib.h>
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler_util.h"
|
#include "taler_util.h"
|
||||||
#include "taler_json_lib.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.
|
* Send JSON object as response.
|
||||||
*
|
*
|
||||||
@ -61,12 +130,26 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
|
|||||||
unsigned int response_code)
|
unsigned int response_code)
|
||||||
{
|
{
|
||||||
struct MHD_Response *resp;
|
struct MHD_Response *resp;
|
||||||
char *json_str;
|
void *json_str;
|
||||||
|
size_t json_len;
|
||||||
int ret;
|
int ret;
|
||||||
|
int comp;
|
||||||
|
|
||||||
json_str = json_dumps (json, JSON_INDENT(2));
|
json_str = json_dumps (json,
|
||||||
GNUNET_assert (NULL != json_str);
|
JSON_INDENT(2));
|
||||||
resp = MHD_create_response_from_buffer (strlen (json_str),
|
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,
|
json_str,
|
||||||
MHD_RESPMEM_MUST_FREE);
|
MHD_RESPMEM_MUST_FREE);
|
||||||
if (NULL == resp)
|
if (NULL == resp)
|
||||||
@ -79,6 +162,19 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
|
|||||||
(void) MHD_add_response_header (resp,
|
(void) MHD_add_response_header (resp,
|
||||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||||
"application/json");
|
"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,
|
ret = MHD_queue_response (connection,
|
||||||
response_code,
|
response_code,
|
||||||
resp);
|
resp);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "taler-exchange-httpd.h"
|
#include "taler-exchange-httpd.h"
|
||||||
#include "taler-exchange-httpd_db.h"
|
#include "taler-exchange-httpd_db.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add headers we want to return in every response.
|
* Add headers we want to return in every response.
|
||||||
* Useful for testing, like if we want to always close
|
* Useful for testing, like if we want to always close
|
||||||
@ -44,6 +45,28 @@ void
|
|||||||
TEH_RESPONSE_add_global_headers (struct MHD_Response *response);
|
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.
|
* Send JSON object as response.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user