add some hooks to be able to cache hits to googles online mp3 apis with mod_httapi e.g. http://(ext=mp3,user_agent='Mozilla/5.0 (X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1')translate.google.com/translate_tts?q=this+is+a+test

This commit is contained in:
Anthony Minessale 2012-01-25 11:46:46 -06:00
parent 39c4e7a320
commit 6e95a146af
2 changed files with 81 additions and 33 deletions

View File

@ -88,6 +88,7 @@ typedef struct client_profile_s {
int auth_scheme; int auth_scheme;
int timeout; int timeout;
profile_perms_t perms; profile_perms_t perms;
char *ua;
struct { struct {
char *use_profile; char *use_profile;
@ -171,9 +172,15 @@ struct http_file_context {
switch_file_t *lock_fd; switch_file_t *lock_fd;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
int del_on_close; int del_on_close;
char *dest_url;
char *ua;
switch_event_t *url_params;
struct {
char *ext;
} read;
struct { struct {
char *dest_url;
char *params;
char *file_name; char *file_name;
char *profile_name; char *profile_name;
char *file; char *file;
@ -1301,8 +1308,9 @@ static switch_status_t httapi_sync(client_t *client)
switch_event_t *save_params = NULL; switch_event_t *save_params = NULL;
const char *put_file; const char *put_file;
FILE *fd = NULL; FILE *fd = NULL;
char *creds, *dup_creds = NULL; char *creds, *dup_creds = NULL, *ua = NULL;
if (client->one_time_params && client->one_time_params->headers) { if (client->one_time_params && client->one_time_params->headers) {
save_params = client->params; save_params = client->params;
switch_event_dup(&client->params, save_params); switch_event_dup(&client->params, save_params);
@ -1311,6 +1319,13 @@ static switch_status_t httapi_sync(client_t *client)
switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE); switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE);
client->one_time_params->flags |= EF_UNIQ_HEADERS; client->one_time_params->flags |= EF_UNIQ_HEADERS;
} }
ua = switch_event_get_header(client->params, "user_agent");
if (zstr(ua)) {
ua = client->profile->ua;
}
if (!(session_id = switch_event_get_header(client->params, "HTTAPI_SESSION_ID"))) { if (!(session_id = switch_event_get_header(client->params, "HTTAPI_SESSION_ID"))) {
if (client->channel && !(session_id = switch_channel_get_variable(client->channel, "HTTAPI_SESSION_ID"))) { if (client->channel && !(session_id = switch_channel_get_variable(client->channel, "HTTAPI_SESSION_ID"))) {
@ -1465,7 +1480,7 @@ static switch_status_t httapi_sync(client_t *client)
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "mod_httapi/1.0"); switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua);
if (client->profile->timeout) { if (client->profile->timeout) {
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout); switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout);
@ -1509,7 +1524,7 @@ static switch_status_t httapi_sync(client_t *client)
curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local); curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local);
} }
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "mod_httapi/1.0");
switch_curl_easy_perform(curl_handle); switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &client->code); switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &client->code);
switch_curl_easy_cleanup(curl_handle); switch_curl_easy_cleanup(curl_handle);
@ -1610,6 +1625,7 @@ static switch_status_t do_config(void)
char *ssl_cacert_file = NULL; char *ssl_cacert_file = NULL;
uint32_t enable_ssl_verifyhost = 0; uint32_t enable_ssl_verifyhost = 0;
char *cookie_file = NULL; char *cookie_file = NULL;
char *ua = "mod_httapi/1.0";
hash_node_t *hash_node; hash_node_t *hash_node;
int auth_scheme = CURLAUTH_BASIC; int auth_scheme = CURLAUTH_BASIC;
need_vars_map = 0; need_vars_map = 0;
@ -1634,6 +1650,8 @@ static switch_status_t do_config(void)
if (val) { if (val) {
url = val; url = val;
} }
} else if (!strcasecmp(var, "user-agent")) {
ua = val;
} else if (!strcasecmp(var, "gateway-credentials")) { } else if (!strcasecmp(var, "gateway-credentials")) {
bind_cred = val; bind_cred = val;
} else if (!strcasecmp(var, "auth-scheme")) { } else if (!strcasecmp(var, "auth-scheme")) {
@ -1715,11 +1733,14 @@ static switch_status_t do_config(void)
} }
memset(profile, 0, sizeof(*profile)); memset(profile, 0, sizeof(*profile));
/* Defaults */ /* Defaults */
profile->ua = ua;
profile->conference_params.use_profile = "default"; profile->conference_params.use_profile = "default";
profile->perms.set_params = 1; profile->perms.set_params = 1;
profile->perms.conference.enabled = 1; profile->perms.conference.enabled = 1;
profile->perms.dial.enabled = 1; profile->perms.dial.enabled = 1;
if ((tag = switch_xml_child(profile_tag, "conference"))) { if ((tag = switch_xml_child(profile_tag, "conference"))) {
for (param = switch_xml_child(tag, "param"); param; param = param->next) { for (param = switch_xml_child(tag, "param"); param; param = param->next) {
@ -2175,18 +2196,24 @@ SWITCH_STANDARD_APP(httapi_function)
static char *load_cache_data(http_file_context_t *context, const char *url) static char *load_cache_data(http_file_context_t *context, const char *url)
{ {
char *ext; char *ext = NULL;
char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };
char meta_buffer[1024] = ""; char meta_buffer[1024] = "";
int fd; int fd;
switch_ssize_t bytes; switch_ssize_t bytes;
switch_md5_string(digest, (void *) url, strlen(url)); switch_md5_string(digest, (void *) url, strlen(url));
if (context->url_params) {
ext = switch_event_get_header(context->url_params, "ext");
}
if ((ext = strrchr(url, '.'))) { if (zstr(ext)) {
ext++; if ((ext = strrchr(url, '.'))) {
} else { ext++;
ext = "wav"; } else {
ext = "wav";
}
} }
context->cache_file = switch_core_sprintf(context->pool, "%s%s%s.%s", globals.cache_path, SWITCH_PATH_SEPARATOR, digest, ext); context->cache_file = switch_core_sprintf(context->pool, "%s%s%s.%s", globals.cache_path, SWITCH_PATH_SEPARATOR, digest, ext);
@ -2235,13 +2262,15 @@ static size_t save_file_callback(void *ptr, size_t size, size_t nmemb, void *dat
static switch_status_t fetch_cache_data(const char *url, switch_event_t **headers, const char *save_path) static switch_status_t fetch_cache_data(http_file_context_t *context, const char *url, switch_event_t **headers, const char *save_path)
{ {
switch_CURL *curl_handle = NULL; switch_CURL *curl_handle = NULL;
client_t client = { 0 }; client_t client = { 0 };
long code; long code;
switch_status_t status = SWITCH_STATUS_FALSE; switch_status_t status = SWITCH_STATUS_FALSE;
char *dup_creds = NULL, *dynamic_url = NULL, *use_url; char *dup_creds = NULL, *dynamic_url = NULL, *use_url;
char *ua = NULL;
client.fd = -1; client.fd = -1;
if (save_path) { if (save_path) {
@ -2249,7 +2278,14 @@ static switch_status_t fetch_cache_data(const char *url, switch_event_t **header
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
} }
if (context->url_params) {
ua = switch_event_get_header(context->url_params, "user_agent");
}
if (zstr(ua)) {
ua = "mod_httapi/1.0";
}
if ((use_url = strchr(url, '@'))) { if ((use_url = strchr(url, '@'))) {
char *r, *q, *p = strstr(url, "://"); char *r, *q, *p = strstr(url, "://");
@ -2312,7 +2348,7 @@ static switch_status_t fetch_cache_data(const char *url, switch_event_t **header
switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, dup_creds); switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, dup_creds);
} }
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "mod_httapi/1.0"); switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua);
switch_curl_easy_perform(curl_handle); switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code); switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
switch_curl_easy_cleanup(curl_handle); switch_curl_easy_cleanup(curl_handle);
@ -2442,7 +2478,7 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char
lock_file(context, SWITCH_TRUE); lock_file(context, SWITCH_TRUE);
if ((status = fetch_cache_data(url, &headers, NULL)) != SWITCH_STATUS_SUCCESS) { if ((status = fetch_cache_data(context, url, &headers, NULL)) != SWITCH_STATUS_SUCCESS) {
if (status == SWITCH_STATUS_NOTFOUND) { if (status == SWITCH_STATUS_NOTFOUND) {
unreachable = 2; unreachable = 2;
if (now - context->expires < globals.not_found_expires) { if (now - context->expires < globals.not_found_expires) {
@ -2473,7 +2509,7 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char
} }
switch_event_destroy(&headers); switch_event_destroy(&headers);
fetch_cache_data(url, &headers, context->cache_file); fetch_cache_data(context, url, &headers, context->cache_file);
metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s", metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s",
url, url,
switch_event_get_header_nil(headers, "last-modified"), switch_event_get_header_nil(headers, "last-modified"),
@ -2517,15 +2553,26 @@ static switch_status_t http_file_file_seek(switch_file_handle_t *handle, unsigne
static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path) static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path)
{ {
http_file_context_t *context; http_file_context_t *context;
char *file_dup; char *parsed = NULL, *pdup = NULL;
switch_status_t status; switch_status_t status;
context = switch_core_alloc(handle->memory_pool, sizeof(*context)); context = switch_core_alloc(handle->memory_pool, sizeof(*context));
context->pool = handle->memory_pool; context->pool = handle->memory_pool;
pdup = switch_core_strdup(context->pool, path);
switch_event_create_brackets(pdup, '(', ')', ',', &context->url_params, &parsed, SWITCH_FALSE);
if (context->url_params) {
context->ua = switch_event_get_header(context->url_params, "ua");
}
if (parsed) path = parsed;
context->dest_url = switch_core_sprintf(context->pool, "http://%s", path);
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
char *ext; char *ext;
context->fh.channels = handle->channels; context->fh.channels = handle->channels;
context->fh.native_rate = handle->native_rate; context->fh.native_rate = handle->native_rate;
@ -2533,19 +2580,17 @@ static switch_status_t http_file_file_open(switch_file_handle_t *handle, const c
context->fh.samplerate = handle->samplerate; context->fh.samplerate = handle->samplerate;
context->fh.prefix = handle->prefix; context->fh.prefix = handle->prefix;
context->write.dest_url = switch_core_sprintf(context->pool, "http://%s", path);
if (context->url_params) {
if ((context->write.params = strchr(context->write.dest_url, ';'))) { context->write.file_name = switch_event_get_header(context->url_params, "file");
*context->write.params++ = '\0'; context->write.profile_name = switch_event_get_header(context->url_params, "profile");
context->write.file_name = switch_find_parameter(context->write.params, "file", context->pool); context->write.method = switch_event_get_header(context->url_params, "method");
context->write.profile_name = switch_find_parameter(context->write.params, "profile", context->pool); context->write.name = switch_event_get_header(context->url_params, "name");
context->write.method = switch_find_parameter(context->write.params, "method", context->pool);
context->write.name = switch_find_parameter(context->write.params, "name", context->pool);
} }
if (!context->write.file_name) { if (!context->write.file_name) {
char *p; char *p;
if ((p = strrchr(context->write.dest_url, '/'))) { if ((p = strrchr(context->dest_url, '/'))) {
p++; p++;
context->write.file_name = switch_core_strdup(context->pool, p); context->write.file_name = switch_core_strdup(context->pool, p);
} }
@ -2573,14 +2618,13 @@ static switch_status_t http_file_file_open(switch_file_handle_t *handle, const c
} else { } else {
if (context->url_params) {
file_dup = switch_core_sprintf(handle->memory_pool, "http://%s", path); context->read.ext = switch_event_get_header(context->url_params, "ext");
if ((status = locate_url_file(context, file_dup)) != SWITCH_STATUS_SUCCESS) {
return status;
} }
if ((status = locate_url_file(context, context->dest_url)) != SWITCH_STATUS_SUCCESS) {
return status;
}
if ((status = switch_core_file_open(&context->fh, if ((status = switch_core_file_open(&context->fh,
context->cache_file, context->cache_file,
@ -2636,7 +2680,7 @@ static switch_status_t http_file_file_close(switch_file_handle_t *handle)
switch_event_add_header(params, SWITCH_STACK_BOTTOM, key, "%s", context->write.file); switch_event_add_header(params, SWITCH_STACK_BOTTOM, key, "%s", context->write.file);
} }
switch_event_add_header(params, SWITCH_STACK_BOTTOM, "url", "%s", context->write.dest_url); switch_event_add_header(params, SWITCH_STACK_BOTTOM, "url", "%s", context->dest_url);
switch_event_add_header(params, SWITCH_STACK_BOTTOM, "file_driver", "true"); switch_event_add_header(params, SWITCH_STACK_BOTTOM, "file_driver", "true");
switch_event_add_header(params, SWITCH_STACK_BOTTOM, "HTTAPI_SESSION_ID", "%s", context->write.uuid_str); switch_event_add_header(params, SWITCH_STACK_BOTTOM, "HTTAPI_SESSION_ID", "%s", context->write.uuid_str);
@ -2661,6 +2705,10 @@ static switch_status_t http_file_file_close(switch_file_handle_t *handle)
} }
} }
if (context->url_params) {
switch_event_destroy(&context->url_params);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -300,7 +300,7 @@ cookie-file : <string> "" Path to
enable-post-var : <param_name> "" Specify specifc param names ok to send. enable-post-var : <param_name> "" Specify specifc param names ok to send.
bind-local : <string> "" Interface to bind to. bind-local : <string> "" Interface to bind to.
default-profile : <string> default Profile to use when not specified. default-profile : <string> default Profile to use when not specified.
user-agent : <string> mod_httapi/1.0 User Agent header value.
<permissions>: * = default <permissions>: * = default