[http/spotify] Add support for http sessions across multiple requests
This change allows to reuse curl handles for multiple requests. Reusing a curl handle improves performance if more than one request is made against a service (connection, session cache, dns cache are kept between requests).
This commit is contained in:
parent
8531a27235
commit
d277f7c7b3
|
@ -439,7 +439,7 @@ artwork_read_byurl(struct evbuffer *evbuf, const char *url)
|
|||
client.input_headers = kv;
|
||||
client.input_body = evbuf;
|
||||
|
||||
ret = http_client_request(&client);
|
||||
ret = http_client_request(&client, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_ART, "Request to '%s' failed with return value %d\n", url, ret);
|
||||
|
@ -1288,7 +1288,7 @@ online_source_search(struct online_source *src, struct artwork_ctx *ctx)
|
|||
client.url = url;
|
||||
client.output_headers = &output_headers;
|
||||
|
||||
ret = http_client_request(&client);
|
||||
ret = http_client_request(&client, NULL);
|
||||
keyval_clear(&output_headers);
|
||||
if (ret < 0 || client.response_code != HTTP_OK)
|
||||
{
|
||||
|
|
37
src/http.c
37
src/http.c
|
@ -55,6 +55,19 @@
|
|||
// Number of seconds the client will wait for a response before aborting
|
||||
#define HTTP_CLIENT_TIMEOUT 8
|
||||
|
||||
|
||||
void
|
||||
http_client_session_init(struct http_client_session *session)
|
||||
{
|
||||
session->curl = curl_easy_init();
|
||||
}
|
||||
|
||||
void
|
||||
http_client_session_deinit(struct http_client_session *session)
|
||||
{
|
||||
curl_easy_cleanup(session->curl);
|
||||
}
|
||||
|
||||
static void
|
||||
curl_headers_save(struct keyval *kv, CURL *curl)
|
||||
{
|
||||
|
@ -95,7 +108,7 @@ curl_request_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|||
}
|
||||
|
||||
int
|
||||
http_client_request(struct http_client_ctx *ctx)
|
||||
http_client_request(struct http_client_ctx *ctx, struct http_client_session *session)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
@ -106,7 +119,15 @@ http_client_request(struct http_client_ctx *ctx)
|
|||
char header[1024];
|
||||
long response_code;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (session)
|
||||
{
|
||||
curl = session->curl;
|
||||
curl_easy_reset(curl);
|
||||
}
|
||||
else
|
||||
{
|
||||
curl = curl_easy_init();
|
||||
}
|
||||
if (!curl)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTP, "Error: Could not get curl handle\n");
|
||||
|
@ -153,7 +174,10 @@ http_client_request(struct http_client_ctx *ctx)
|
|||
{
|
||||
DPRINTF(E_LOG, L_HTTP, "Request to %s failed: %s\n", ctx->url, curl_easy_strerror(res));
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
if (!session)
|
||||
{
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -162,7 +186,10 @@ http_client_request(struct http_client_ctx *ctx)
|
|||
curl_headers_save(ctx->input_headers, curl);
|
||||
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
if (!session)
|
||||
{
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -262,7 +289,7 @@ http_stream_setup(char **stream, const char *url)
|
|||
ctx.url = url;
|
||||
ctx.input_body = evbuf;
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTP, "Couldn't fetch internet playlist: %s\n", url);
|
||||
|
|
13
src/http.h
13
src/http.h
|
@ -4,10 +4,16 @@
|
|||
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/http.h>
|
||||
#include <curl/curl.h>
|
||||
#include "misc.h"
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
struct http_client_session
|
||||
{
|
||||
CURL *curl;
|
||||
};
|
||||
|
||||
struct http_client_ctx
|
||||
{
|
||||
/* Destination URL, header and body of outgoing request body. If output_body
|
||||
|
@ -54,6 +60,11 @@ struct http_icy_metadata
|
|||
uint32_t hash;
|
||||
};
|
||||
|
||||
void
|
||||
http_client_session_init(struct http_client_session *session);
|
||||
|
||||
void
|
||||
http_client_session_deinit(struct http_client_session *session);
|
||||
|
||||
/* Make a http(s) request. We use libcurl to make https requests. We could use
|
||||
* libevent and avoid the dependency, but for SSL, libevent needs to be v2.1
|
||||
|
@ -63,7 +74,7 @@ struct http_icy_metadata
|
|||
* @return 0 if successful, -1 if an error occurred (e.g. no libcurl)
|
||||
*/
|
||||
int
|
||||
http_client_request(struct http_client_ctx *ctx);
|
||||
http_client_request(struct http_client_ctx *ctx, struct http_client_session *session);
|
||||
|
||||
|
||||
/* Converts the keyval dictionary to a application/x-www-form-urlencoded string.
|
||||
|
|
|
@ -194,7 +194,7 @@ streamurl_process(struct input_metadata *metadata, const char *url)
|
|||
client.input_headers = &kv;
|
||||
client.input_body = evbuf;
|
||||
|
||||
ret = http_client_request(&client);
|
||||
ret = http_client_request(&client, NULL);
|
||||
if (ret < 0 || client.response_code != HTTP_OK)
|
||||
{
|
||||
DPRINTF(E_WARN, L_PLAYER, "Request for StreamUrl resource '%s' failed, response code %d\n", url, client.response_code);
|
||||
|
|
|
@ -228,7 +228,7 @@ https_get_cb(char **out, const char *url)
|
|||
ctx.url = url;
|
||||
ctx.input_body = evbuffer_new();
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0 || ctx.response_code != HTTP_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Failed to AP list from '%s' (return %d, error code %d)\n", ctx.url, ret, ctx.response_code);
|
||||
|
|
|
@ -239,7 +239,7 @@ request_post(const char *url, struct keyval *kv, char **errmsg)
|
|||
ctx.url = url;
|
||||
ctx.input_body = evbuffer_new();
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0)
|
||||
goto out_free_ctx;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ apple_rss_feedurl_get(const char *rss_url)
|
|||
ctx.url = url;
|
||||
ctx.input_body = evbuf;
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0 || ctx.response_code != HTTP_OK)
|
||||
{
|
||||
evbuffer_free(evbuf);
|
||||
|
@ -256,7 +256,7 @@ rss_xml_get(const char *url)
|
|||
CHECK_NULL(L_LIB, ctx.input_body = evbuffer_new());
|
||||
ctx.url = feedurl;
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0 || ctx.response_code != HTTP_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_LIB, "Failed to fetch RSS from '%s' (return %d, error code %d)\n", ctx.url, ret, ctx.response_code);
|
||||
|
|
|
@ -166,6 +166,7 @@ static const char *spotify_shows_uri = "https://api.spotify.com/v1/me/
|
|||
static const char *spotify_shows_episodes_uri = "https://api.spotify.com/v1/shows/%s/episodes";
|
||||
static const char *spotify_episode_uri = "https://api.spotify.com/v1/episodes/%s";
|
||||
|
||||
static struct http_client_session session = { 0 };
|
||||
|
||||
static enum spotify_item_type
|
||||
parse_type_from_uri(const char *uri)
|
||||
|
@ -256,7 +257,7 @@ request_access_tokens(struct keyval *kv, const char **err)
|
|||
ctx.output_body = param;
|
||||
ctx.input_body = evbuffer_new();
|
||||
|
||||
ret = http_client_request(&ctx);
|
||||
ret = http_client_request(&ctx, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
*err = "Did not get a reply from Spotify";
|
||||
|
@ -366,7 +367,7 @@ request_endpoint(const char *uri)
|
|||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Request Spotify API endpoint: '%s')\n", uri);
|
||||
|
||||
ret = http_client_request(ctx);
|
||||
ret = http_client_request(ctx, &session);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Request for '%s' failed\n", uri);
|
||||
|
@ -2321,10 +2322,15 @@ spotifywebapi_access_token_get(struct spotifywebapi_access_token *info)
|
|||
static int
|
||||
spotifywebapi_init()
|
||||
{
|
||||
CHECK_ERR(L_SPOTIFY, mutex_init(&token_lck));
|
||||
int ret;
|
||||
|
||||
// Required for libspotify backend
|
||||
return spotify_init();
|
||||
CHECK_ERR(L_SPOTIFY, mutex_init(&token_lck));
|
||||
ret = spotify_init();
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
http_client_session_init(&session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2333,6 +2339,7 @@ spotifywebapi_deinit()
|
|||
CHECK_ERR(L_SPOTIFY, pthread_mutex_destroy(&token_lck));
|
||||
|
||||
spotify_deinit();
|
||||
http_client_session_deinit(&session);
|
||||
|
||||
free_credentials();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue