add Etag and 'expires' to /wire
This commit is contained in:
parent
6cf4a068ad
commit
75d9584e28
@ -1656,58 +1656,6 @@ add_denom_key_cb (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Produce HTTP "Date:" header.
|
||||
*
|
||||
* @param at time to write to @a date
|
||||
* @param[out] date where to write the header, with
|
||||
* at least 128 bytes available space.
|
||||
*/
|
||||
static void
|
||||
get_date_string (struct GNUNET_TIME_Absolute at,
|
||||
char date[128])
|
||||
{
|
||||
static const char *const days[] =
|
||||
{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char *const mons[] =
|
||||
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
||||
"Nov", "Dec"};
|
||||
struct tm now;
|
||||
time_t t;
|
||||
#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
|
||||
! defined(HAVE_GMTIME_R)
|
||||
struct tm*pNow;
|
||||
#endif
|
||||
|
||||
date[0] = 0;
|
||||
t = (time_t) (at.abs_value_us / 1000LL / 1000LL);
|
||||
#if defined(HAVE_C11_GMTIME_S)
|
||||
if (NULL == gmtime_s (&t, &now))
|
||||
return;
|
||||
#elif defined(HAVE_W32_GMTIME_S)
|
||||
if (0 != gmtime_s (&now, &t))
|
||||
return;
|
||||
#elif defined(HAVE_GMTIME_R)
|
||||
if (NULL == gmtime_r (&t, &now))
|
||||
return;
|
||||
#else
|
||||
pNow = gmtime (&t);
|
||||
if (NULL == pNow)
|
||||
return;
|
||||
now = *pNow;
|
||||
#endif
|
||||
sprintf (date,
|
||||
"%3s, %02u %3s %04u %02u:%02u:%02u GMT",
|
||||
days[now.tm_wday % 7],
|
||||
(unsigned int) now.tm_mday,
|
||||
mons[now.tm_mon % 12],
|
||||
(unsigned int) (1900 + now.tm_year),
|
||||
(unsigned int) now.tm_hour,
|
||||
(unsigned int) now.tm_min,
|
||||
(unsigned int) now.tm_sec);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the headers we want to set for every /keys response.
|
||||
*
|
||||
@ -1726,8 +1674,8 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_CONTENT_TYPE,
|
||||
"application/json"));
|
||||
get_date_string (ksh->reload_time.abs_time,
|
||||
dat);
|
||||
TALER_MHD_get_date_string (ksh->reload_time.abs_time,
|
||||
dat);
|
||||
GNUNET_break (MHD_YES ==
|
||||
MHD_add_response_header (response,
|
||||
MHD_HTTP_HEADER_LAST_MODIFIED,
|
||||
@ -1742,8 +1690,8 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
|
||||
ksh->rekey_frequency);
|
||||
a = GNUNET_TIME_relative_to_absolute (r);
|
||||
m = GNUNET_TIME_absolute_to_timestamp (a);
|
||||
get_date_string (m.abs_time,
|
||||
dat);
|
||||
TALER_MHD_get_date_string (m.abs_time,
|
||||
dat);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Setting /keys 'Expires' header to '%s'\n",
|
||||
dat);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2021 Taler Systems SA
|
||||
Copyright (C) 2015-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -72,9 +72,9 @@ struct WireFeeSet
|
||||
struct WireStateHandle
|
||||
{
|
||||
/**
|
||||
* Cached JSON for /wire response.
|
||||
* Cached reply for /wire response.
|
||||
*/
|
||||
json_t *wire_reply;
|
||||
struct MHD_Response *wire_reply;
|
||||
|
||||
/**
|
||||
* head of DLL of wire fees.
|
||||
@ -136,7 +136,7 @@ destroy_wire_state (struct WireStateHandle *wsh)
|
||||
GNUNET_free (wfs->method);
|
||||
GNUNET_free (wfs);
|
||||
}
|
||||
json_decref (wsh->wire_reply);
|
||||
MHD_destroy_response (wsh->wire_reply);
|
||||
GNUNET_free (wsh);
|
||||
}
|
||||
|
||||
@ -203,28 +203,6 @@ TEH_wire_done ()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create standard JSON response format using @a ec and @a detail.
|
||||
*
|
||||
* @param ec error code to return
|
||||
* @param detail optional detail text to return, can be NULL
|
||||
* @return JSON response
|
||||
*/
|
||||
static json_t *
|
||||
make_ec_reply (enum TALER_ErrorCode ec,
|
||||
const char *detail)
|
||||
{
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("code",
|
||||
ec),
|
||||
GNUNET_JSON_pack_string ("hint",
|
||||
TALER_ErrorCode_get_hint (ec)),
|
||||
GNUNET_JSON_pack_allow_null (
|
||||
GNUNET_JSON_pack_string ("detail",
|
||||
detail)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add information about a wire account to @a cls.
|
||||
*
|
||||
@ -274,6 +252,18 @@ struct AddContext
|
||||
* Array to append the fee to.
|
||||
*/
|
||||
json_t *a;
|
||||
|
||||
/**
|
||||
* Context we hash "everything" we add into. This is used
|
||||
* to compute the etag. Technically, we only hash the
|
||||
* master_sigs, as they imply the rest.
|
||||
*/
|
||||
struct GNUNET_HashContext *hc;
|
||||
|
||||
/**
|
||||
* Set to the maximum end-date seen.
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute max_seen;
|
||||
};
|
||||
|
||||
|
||||
@ -297,6 +287,11 @@ add_wire_fee (void *cls,
|
||||
struct AddContext *ac = cls;
|
||||
struct WireFeeSet *wfs;
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (ac->hc,
|
||||
master_sig,
|
||||
sizeof (*master_sig));
|
||||
ac->max_seen = GNUNET_TIME_absolute_max (ac->max_seen,
|
||||
end_date.abs_time);
|
||||
wfs = GNUNET_new (struct WireFeeSet);
|
||||
wfs->start_date = start_date;
|
||||
wfs->end_date = end_date;
|
||||
@ -341,6 +336,8 @@ build_wire_state (void)
|
||||
uint64_t wg = wire_generation; /* must be obtained FIRST */
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct WireStateHandle *wsh;
|
||||
struct GNUNET_TIME_Absolute cache_expiration;
|
||||
struct GNUNET_HashContext *hc;
|
||||
|
||||
wsh = GNUNET_new (struct WireStateHandle);
|
||||
wsh->wire_generation = wg;
|
||||
@ -355,8 +352,8 @@ build_wire_state (void)
|
||||
json_decref (wire_accounts_array);
|
||||
wsh->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
wsh->wire_reply
|
||||
= make_ec_reply (TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_wire_accounts");
|
||||
= TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_wire_accounts");
|
||||
return wsh;
|
||||
}
|
||||
if (0 == json_array_size (wire_accounts_array))
|
||||
@ -364,12 +361,14 @@ build_wire_state (void)
|
||||
json_decref (wire_accounts_array);
|
||||
wsh->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
wsh->wire_reply
|
||||
= make_ec_reply (TALER_EC_EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED,
|
||||
NULL);
|
||||
= TALER_MHD_make_error (TALER_EC_EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED,
|
||||
NULL);
|
||||
return wsh;
|
||||
}
|
||||
wire_fee_object = json_object ();
|
||||
GNUNET_assert (NULL != wire_fee_object);
|
||||
cache_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
|
||||
hc = GNUNET_CRYPTO_hash_context_start ();
|
||||
{
|
||||
json_t *account;
|
||||
size_t index;
|
||||
@ -385,10 +384,12 @@ build_wire_state (void)
|
||||
{
|
||||
wsh->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
wsh->wire_reply
|
||||
= make_ec_reply (TALER_EC_EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED,
|
||||
payto_uri);
|
||||
= TALER_MHD_make_error (
|
||||
TALER_EC_EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED,
|
||||
payto_uri);
|
||||
json_decref (wire_accounts_array);
|
||||
json_decref (wire_fee_object);
|
||||
GNUNET_CRYPTO_hash_context_abort (hc);
|
||||
return wsh;
|
||||
}
|
||||
if (NULL == json_object_get (wire_fee_object,
|
||||
@ -397,7 +398,8 @@ build_wire_state (void)
|
||||
struct AddContext ac = {
|
||||
.wire_method = wire_method,
|
||||
.wsh = wsh,
|
||||
.a = json_array ()
|
||||
.a = json_array (),
|
||||
.hc = hc
|
||||
};
|
||||
|
||||
GNUNET_assert (NULL != ac.a);
|
||||
@ -414,8 +416,9 @@ build_wire_state (void)
|
||||
GNUNET_free (wire_method);
|
||||
wsh->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
wsh->wire_reply
|
||||
= make_ec_reply (TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_wire_fees");
|
||||
= TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_wire_fees");
|
||||
GNUNET_CRYPTO_hash_context_abort (hc);
|
||||
return wsh;
|
||||
}
|
||||
if (0 == json_array_size (ac.a))
|
||||
@ -425,11 +428,14 @@ build_wire_state (void)
|
||||
json_decref (wire_fee_object);
|
||||
wsh->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||
wsh->wire_reply
|
||||
= make_ec_reply (TALER_EC_EXCHANGE_WIRE_FEES_NOT_CONFIGURED,
|
||||
wire_method);
|
||||
= TALER_MHD_make_error (TALER_EC_EXCHANGE_WIRE_FEES_NOT_CONFIGURED,
|
||||
wire_method);
|
||||
GNUNET_free (wire_method);
|
||||
GNUNET_CRYPTO_hash_context_abort (hc);
|
||||
return wsh;
|
||||
}
|
||||
cache_expiration = GNUNET_TIME_absolute_min (ac.max_seen,
|
||||
cache_expiration);
|
||||
GNUNET_assert (0 ==
|
||||
json_object_set_new (wire_fee_object,
|
||||
wire_method,
|
||||
@ -438,13 +444,48 @@ build_wire_state (void)
|
||||
GNUNET_free (wire_method);
|
||||
}
|
||||
}
|
||||
wsh->wire_reply = GNUNET_JSON_PACK (
|
||||
|
||||
|
||||
wsh->wire_reply = TALER_MHD_MAKE_JSON_PACK (
|
||||
GNUNET_JSON_pack_array_steal ("accounts",
|
||||
wire_accounts_array),
|
||||
GNUNET_JSON_pack_object_steal ("fees",
|
||||
wire_fee_object),
|
||||
GNUNET_JSON_pack_data_auto ("master_public_key",
|
||||
&TEH_master_public_key));
|
||||
{
|
||||
char dat[128];
|
||||
struct GNUNET_TIME_Timestamp m;
|
||||
|
||||
m = GNUNET_TIME_absolute_to_timestamp (cache_expiration);
|
||||
TALER_MHD_get_date_string (m.abs_time,
|
||||
dat);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Setting 'Expires' header for '/wire' to '%s'\n",
|
||||
dat);
|
||||
GNUNET_break (MHD_YES ==
|
||||
MHD_add_response_header (wsh->wire_reply,
|
||||
MHD_HTTP_HEADER_EXPIRES,
|
||||
dat));
|
||||
}
|
||||
TALER_MHD_add_global_headers (wsh->wire_reply);
|
||||
{
|
||||
struct GNUNET_HashCode h;
|
||||
char etag[sizeof (h) * 2];
|
||||
char *end;
|
||||
|
||||
GNUNET_CRYPTO_hash_context_finish (hc,
|
||||
&h);
|
||||
end = GNUNET_STRINGS_data_to_string (&h,
|
||||
sizeof (h),
|
||||
etag,
|
||||
sizeof (etag));
|
||||
*end = '\0';
|
||||
GNUNET_break (MHD_YES ==
|
||||
MHD_add_response_header (wsh->wire_reply,
|
||||
MHD_HTTP_HEADER_ETAG,
|
||||
etag));
|
||||
}
|
||||
wsh->http_status = MHD_HTTP_OK;
|
||||
return wsh;
|
||||
}
|
||||
@ -509,9 +550,9 @@ TEH_handler_wire (struct TEH_RequestContext *rc,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
||||
NULL);
|
||||
return TALER_MHD_reply_json (rc->connection,
|
||||
wsh->wire_reply,
|
||||
wsh->http_status);
|
||||
return MHD_queue_response (rc->connection,
|
||||
wsh->http_status,
|
||||
wsh->wire_reply);
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,6 +207,18 @@ TALER_MHD_reply_with_ec (struct MHD_Connection *connection,
|
||||
const char *detail);
|
||||
|
||||
|
||||
/**
|
||||
* Produce HTTP "Date:" header.
|
||||
*
|
||||
* @param at time to write to @a date
|
||||
* @param[out] date where to write the header, with
|
||||
* at least 128 bytes available space.
|
||||
*/
|
||||
void
|
||||
TALER_MHD_get_date_string (struct GNUNET_TIME_Absolute at,
|
||||
char date[128]);
|
||||
|
||||
|
||||
/**
|
||||
* Make JSON response object.
|
||||
*
|
||||
|
@ -178,8 +178,8 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn,
|
||||
|
||||
a = GNUNET_TIME_relative_to_absolute (MAX_TERMS_CACHING);
|
||||
m = GNUNET_TIME_absolute_to_timestamp (a);
|
||||
get_date_string (m.abs_time,
|
||||
dat);
|
||||
TALER_MHD_get_date_string (m.abs_time,
|
||||
dat);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Setting 'Expires' header to '%s'\n",
|
||||
dat);
|
||||
|
@ -502,4 +502,49 @@ TALER_MHD_reply_static (struct MHD_Connection *connection,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_MHD_get_date_string (struct GNUNET_TIME_Absolute at,
|
||||
char date[128])
|
||||
{
|
||||
static const char *const days[] =
|
||||
{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char *const mons[] =
|
||||
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
||||
"Nov", "Dec"};
|
||||
struct tm now;
|
||||
time_t t;
|
||||
#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
|
||||
! defined(HAVE_GMTIME_R)
|
||||
struct tm*pNow;
|
||||
#endif
|
||||
|
||||
date[0] = 0;
|
||||
t = (time_t) (at.abs_value_us / 1000LL / 1000LL);
|
||||
#if defined(HAVE_C11_GMTIME_S)
|
||||
if (NULL == gmtime_s (&t, &now))
|
||||
return;
|
||||
#elif defined(HAVE_W32_GMTIME_S)
|
||||
if (0 != gmtime_s (&now, &t))
|
||||
return;
|
||||
#elif defined(HAVE_GMTIME_R)
|
||||
if (NULL == gmtime_r (&t, &now))
|
||||
return;
|
||||
#else
|
||||
pNow = gmtime (&t);
|
||||
if (NULL == pNow)
|
||||
return;
|
||||
now = *pNow;
|
||||
#endif
|
||||
sprintf (date,
|
||||
"%3s, %02u %3s %04u %02u:%02u:%02u GMT",
|
||||
days[now.tm_wday % 7],
|
||||
(unsigned int) now.tm_mday,
|
||||
mons[now.tm_mon % 12],
|
||||
(unsigned int) (1900 + now.tm_year),
|
||||
(unsigned int) now.tm_hour,
|
||||
(unsigned int) now.tm_min,
|
||||
(unsigned int) now.tm_sec);
|
||||
}
|
||||
|
||||
|
||||
/* end of mhd_responses.c */
|
||||
|
Loading…
Reference in New Issue
Block a user