forked from enlightenment/efl
efl_net_dialer_http: special headers and date parse/serialize.
CURL needs some special curl_easy_setopt() calls to enable automatic gzip deflate (CURLOPT_ENCODING) and If-Modified-Since/If-Unmodified-Since logic. As If-Modified-Since/If-Unmodified-Since requires a timestamp string, let's expose class methods to handle those.
This commit is contained in:
parent
5c7b984746
commit
3cf20ea8e8
|
@ -312,6 +312,7 @@ _c_init(void)
|
|||
SYM(curl_slist_free_all);
|
||||
SYM(curl_slist_append);
|
||||
SYM(curl_version_info);
|
||||
SYM(curl_getdate);
|
||||
|
||||
_c_init_errors();
|
||||
|
||||
|
|
|
@ -446,6 +446,7 @@ struct _Ecore_Con_Curl
|
|||
void (*curl_slist_free_all)(struct curl_slist *);
|
||||
struct curl_slist *(*curl_slist_append)(struct curl_slist *list,
|
||||
const char *string);
|
||||
time_t (*curl_getdate)(const char *p, const time_t *unused);
|
||||
curl_version_info_data *(*curl_version_info)(CURLversion);
|
||||
};
|
||||
|
||||
|
@ -460,4 +461,8 @@ void _c_shutdown(void);
|
|||
Eina_Error _curlcode_to_eina_error(const CURLcode code);
|
||||
Eina_Error _curlmcode_to_eina_error(const CURLMcode code);
|
||||
|
||||
|
||||
/* only for legacy support to implement behavior that we're not exposing anymore */
|
||||
CURL *efl_net_dialer_http_curl_get(const Eo *o);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define curl_easy_init(...) _c->curl_easy_init(__VA_ARGS__)
|
||||
#define curl_easy_cleanup(...) _c->curl_easy_cleanup(__VA_ARGS__)
|
||||
#define curl_easy_pause(...) _c->curl_easy_pause(__VA_ARGS__)
|
||||
#define curl_getdate(s, unused) _c->curl_getdate(s, unused)
|
||||
|
||||
#ifdef curl_easy_setopt
|
||||
#undef curl_easy_setopt
|
||||
|
@ -1260,6 +1261,7 @@ _efl_net_dialer_http_libproxy_cancel(void *data, Ecore_Thread *thread EINA_UNUSE
|
|||
EOLIAN static Eina_Error
|
||||
_efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, const char *address)
|
||||
{
|
||||
struct curl_slist *sl_it;
|
||||
CURLcode r;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
|
||||
|
@ -1279,6 +1281,77 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co
|
|||
o, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
for (sl_it = pd->request.headers; sl_it != NULL; sl_it = sl_it->next)
|
||||
{
|
||||
#define IS_HEADER(x) (strncasecmp(sl_it->data, x ":", strlen(x ":")) == 0)
|
||||
if (IS_HEADER("Accept-Encoding"))
|
||||
{
|
||||
const char *value = strchr(sl_it->data, ':') + 1;
|
||||
while (*value && isspace(*value))
|
||||
value++;
|
||||
r = curl_easy_setopt(pd->easy, CURLOPT_ENCODING, value);
|
||||
if (r != CURLE_OK)
|
||||
{
|
||||
ERR("dialer=%p could not set HTTP Accept-Encoding '%s': %s",
|
||||
o, value, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
DBG("Using Accept-Encoding: %s", value);
|
||||
}
|
||||
else if (IS_HEADER("If-Modified-Since"))
|
||||
{
|
||||
const char *value = strchr(sl_it->data, ':') + 1;
|
||||
long t;
|
||||
|
||||
r = curl_easy_setopt(pd->easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
|
||||
if (r != CURLE_OK)
|
||||
{
|
||||
ERR("dialer=%p could not set HTTP If-Modified-Since condition: %s",
|
||||
o, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
while (*value && isspace(*value))
|
||||
value++;
|
||||
t = curl_getdate(value, NULL);
|
||||
|
||||
r = curl_easy_setopt(pd->easy, CURLOPT_TIMEVALUE, t);
|
||||
if (r != CURLE_OK)
|
||||
{
|
||||
ERR("dialer=%p could not set HTTP If-Modified-Since value=%ld: %s",
|
||||
o, t, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
DBG("Using If-Modified-Since: %s [t=%ld]", value, t);
|
||||
}
|
||||
else if (IS_HEADER("If-Unmodified-Since"))
|
||||
{
|
||||
const char *value = strchr(sl_it->data, ':') + 1;
|
||||
long t;
|
||||
|
||||
r = curl_easy_setopt(pd->easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFUNMODSINCE);
|
||||
if (r != CURLE_OK)
|
||||
{
|
||||
ERR("dialer=%p could not set HTTP If-Unmodified-Since condition: %s",
|
||||
o, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
while (*value && isspace(*value))
|
||||
value++;
|
||||
t = curl_getdate(value, NULL);
|
||||
|
||||
r = curl_easy_setopt(pd->easy, CURLOPT_TIMEVALUE, t);
|
||||
if (r != CURLE_OK)
|
||||
{
|
||||
ERR("dialer=%p could not set HTTP If-Unmodified-Since value=%ld: %s",
|
||||
o, t, curl_easy_strerror(r));
|
||||
return EINVAL;
|
||||
}
|
||||
DBG("Using If-Unmodified-Since: %s [t=%ld]", value, t);
|
||||
}
|
||||
#undef IS_HEADER
|
||||
}
|
||||
|
||||
if ((!pd->proxy) && (ecore_con_libproxy_init()))
|
||||
{
|
||||
|
@ -2192,6 +2265,36 @@ _efl_net_dialer_http_cookie_jar_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data
|
|||
return pd->cookie_jar;
|
||||
}
|
||||
|
||||
EOLIAN static long
|
||||
_efl_net_dialer_http_date_parse(Efl_Class *cls EINA_UNUSED, void *cd EINA_UNUSED, const char *str)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(str, 0);
|
||||
return curl_getdate(str, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static char *
|
||||
_efl_net_dialer_http_date_serialize(Efl_Class *cls EINA_UNUSED, void *cd EINA_UNUSED, long t)
|
||||
{
|
||||
static const char *const wkday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char * const month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
char buf[128];
|
||||
struct tm *tm, storage;
|
||||
|
||||
tm = gmtime_r(&t, &storage);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(tm, NULL);
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s, %02d %s %4d %02d:%02d:%02d GMT",
|
||||
wkday[tm->tm_wday],
|
||||
tm->tm_mday,
|
||||
month[tm->tm_mon],
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
CURL *
|
||||
efl_net_dialer_http_curl_get(const Eo *o)
|
||||
{
|
||||
|
|
|
@ -334,6 +334,29 @@ class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Sizer) {
|
|||
path: string; [[Path to cookie jar]]
|
||||
}
|
||||
}
|
||||
|
||||
date_parse @class {
|
||||
[[Parse the given string as time in seconds since 1/1/1970.
|
||||
|
||||
This method is useful to parse header values such as
|
||||
"Last-Modified".
|
||||
]]
|
||||
params {
|
||||
str: string; [[String in HTTP text format: Tue, 15 Nov 1994 12:45:26 GMT]]
|
||||
}
|
||||
return: long; [[Seconds since 1/1/1970]]
|
||||
}
|
||||
|
||||
date_serialize @class {
|
||||
[[Serialize the given GMT time in seconds since 1/1/1970.
|
||||
|
||||
The timezone must be GMT (ie: gmtime()).
|
||||
]]
|
||||
params {
|
||||
epochtime: long; [[UNIX Epoch time - seconds since 1/1/1970]]
|
||||
}
|
||||
return: free(own(ptr(char)), free) @warn_unused; [[Newly allocated null-terminated string on success or NULL on errors]]
|
||||
}
|
||||
}
|
||||
|
||||
events {
|
||||
|
|
Loading…
Reference in New Issue