[http] Move Curl https client from lastfm to http so it is available for other modules
This commit is contained in:
parent
575b6e13a8
commit
8c0db10e67
|
@ -1129,8 +1129,8 @@ source_item_stream_get(struct artwork_ctx *ctx)
|
||||||
|
|
||||||
memset(&client, 0, sizeof(struct http_client_ctx));
|
memset(&client, 0, sizeof(struct http_client_ctx));
|
||||||
client.url = url;
|
client.url = url;
|
||||||
client.headers = kv;
|
client.input_headers = kv;
|
||||||
client.body = ctx->evbuf;
|
client.input_body = ctx->evbuf;
|
||||||
|
|
||||||
if (http_client_request(&client) < 0)
|
if (http_client_request(&client) < 0)
|
||||||
goto out_kv;
|
goto out_kv;
|
||||||
|
|
164
src/http.c
164
src/http.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Espen Jürgensen <espenjurgensen@gmail.com>
|
* Copyright (C) 2016 Espen Jürgensen <espenjurgensen@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -36,6 +36,10 @@
|
||||||
|
|
||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
@ -128,10 +132,10 @@ request_cb(struct evhttp_request *req, void *arg)
|
||||||
|
|
||||||
ctx->ret = 0;
|
ctx->ret = 0;
|
||||||
|
|
||||||
if (ctx->headers)
|
if (ctx->input_headers)
|
||||||
headers_save(ctx->headers, evhttp_request_get_input_headers(req));
|
headers_save(ctx->input_headers, evhttp_request_get_input_headers(req));
|
||||||
if (ctx->body)
|
if (ctx->input_body)
|
||||||
evbuffer_add_buffer(ctx->body, evhttp_request_get_input_buffer(req));
|
evbuffer_add_buffer(ctx->input_body, evhttp_request_get_input_buffer(req));
|
||||||
|
|
||||||
event_base_loopbreak(ctx->evbase);
|
event_base_loopbreak(ctx->evbase);
|
||||||
|
|
||||||
|
@ -171,8 +175,8 @@ request_header_cb(struct evhttp_request *req, void *arg)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
static int
|
||||||
http_client_request(struct http_client_ctx *ctx)
|
http_client_request_impl(struct http_client_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct evhttp_connection *evcon;
|
struct evhttp_connection *evcon;
|
||||||
struct evhttp_request *req;
|
struct evhttp_request *req;
|
||||||
|
@ -269,6 +273,144 @@ http_client_request(struct http_client_ctx *ctx)
|
||||||
return ctx->ret;
|
return ctx->ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
static size_t
|
||||||
|
curl_request_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||||
|
{
|
||||||
|
size_t realsize;
|
||||||
|
struct http_client_ctx *ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
realsize = size * nmemb;
|
||||||
|
ctx = (struct http_client_ctx *)userdata;
|
||||||
|
|
||||||
|
if (!ctx->input_body)
|
||||||
|
return realsize;
|
||||||
|
|
||||||
|
ret = evbuffer_add(ctx->input_body, ptr, realsize);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTP, "Error adding reply from %s to input buffer\n", ctx->url);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return realsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
https_client_request_impl(struct http_client_ctx *ctx)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
struct curl_slist *headers;
|
||||||
|
struct onekeyval *okv;
|
||||||
|
char header[1024];
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if (!curl)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTP, "Error: Could not get curl handle\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, ctx->url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "forked-daapd/" VERSION);
|
||||||
|
|
||||||
|
if (ctx->output_headers)
|
||||||
|
{
|
||||||
|
headers = NULL;
|
||||||
|
for (okv = ctx->output_headers->head; okv; okv = okv->next)
|
||||||
|
{
|
||||||
|
snprintf(header, sizeof(header), "%s: %s", okv->name, okv->value);
|
||||||
|
headers = curl_slist_append(headers, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->output_body)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ctx->output_body);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_CLIENT_TIMEOUT);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_request_cb);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
|
||||||
|
|
||||||
|
/* Make request */
|
||||||
|
DPRINTF(E_INFO, L_HTTP, "Making request for %s\n", ctx->url);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
if (res != CURLE_OK)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTP, "Request to %s failed: %s\n", ctx->url, curl_easy_strerror(res));
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
|
int
|
||||||
|
http_client_request(struct http_client_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (strncmp(ctx->url, "http:", strlen("http:")) == 0)
|
||||||
|
return http_client_request_impl(ctx);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
if (strncmp(ctx->url, "https:", strlen("https:")) == 0)
|
||||||
|
return https_client_request_impl(ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DPRINTF(E_LOG, L_HTTP, "Request for %s is not supported (not built with libcurl?)\n", ctx->url);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
http_form_urlencode(struct keyval *kv)
|
||||||
|
{
|
||||||
|
struct evbuffer *evbuf;
|
||||||
|
struct onekeyval *okv;
|
||||||
|
char *body;
|
||||||
|
char *k;
|
||||||
|
char *v;
|
||||||
|
|
||||||
|
evbuf = evbuffer_new();
|
||||||
|
|
||||||
|
for (okv = kv->head; okv; okv = okv->next)
|
||||||
|
{
|
||||||
|
k = evhttp_encode_uri(okv->name);
|
||||||
|
if (!k)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
v = evhttp_encode_uri(okv->value);
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
free(k);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
evbuffer_add_printf(evbuf, "%s=%s", k, v);
|
||||||
|
if (okv->next)
|
||||||
|
evbuffer_add_printf(evbuf, "&");
|
||||||
|
|
||||||
|
free(k);
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
evbuffer_add(evbuf, "\n", 1);
|
||||||
|
|
||||||
|
body = evbuffer_readln(evbuf, NULL, EVBUFFER_EOL_ANY);
|
||||||
|
|
||||||
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_HTTP, "Parameters in request are: %s\n", body);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
http_stream_setup(char **stream, const char *url)
|
http_stream_setup(char **stream, const char *url)
|
||||||
{
|
{
|
||||||
|
@ -296,7 +438,7 @@ http_stream_setup(char **stream, const char *url)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ctx.url = url;
|
ctx.url = url;
|
||||||
ctx.body = evbuf;
|
ctx.input_body = evbuf;
|
||||||
|
|
||||||
ret = http_client_request(&ctx);
|
ret = http_client_request(&ctx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -308,13 +450,13 @@ http_stream_setup(char **stream, const char *url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad with CRLF because evbuffer_readln() might not read the last line otherwise
|
// Pad with CRLF because evbuffer_readln() might not read the last line otherwise
|
||||||
evbuffer_add(ctx.body, "\r\n", 2);
|
evbuffer_add(ctx.input_body, "\r\n", 2);
|
||||||
|
|
||||||
/* Read the playlist until the first stream link is found, but give up if
|
/* Read the playlist until the first stream link is found, but give up if
|
||||||
* nothing is found in the first 10 lines
|
* nothing is found in the first 10 lines
|
||||||
*/
|
*/
|
||||||
n = 0;
|
n = 0;
|
||||||
while ((line = evbuffer_readln(ctx.body, NULL, EVBUFFER_EOL_ANY)) && (n < 10))
|
while ((line = evbuffer_readln(ctx.input_body, NULL, EVBUFFER_EOL_ANY)) && (n < 10))
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
if (strncasecmp(line, "http://", strlen("http://")) == 0)
|
if (strncasecmp(line, "http://", strlen("http://")) == 0)
|
||||||
|
@ -328,7 +470,7 @@ http_stream_setup(char **stream, const char *url)
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
evbuffer_free(ctx.body);
|
evbuffer_free(ctx.input_body);
|
||||||
|
|
||||||
if (n != -1)
|
if (n != -1)
|
||||||
{
|
{
|
||||||
|
|
25
src/http.h
25
src/http.h
|
@ -10,13 +10,18 @@
|
||||||
|
|
||||||
struct http_client_ctx
|
struct http_client_ctx
|
||||||
{
|
{
|
||||||
|
/* Destination URL, header and body of outgoing request body (headers and
|
||||||
|
* body is currently only supported for https)
|
||||||
|
*/
|
||||||
const char *url;
|
const char *url;
|
||||||
|
struct keyval *output_headers;
|
||||||
|
char *output_body;
|
||||||
|
|
||||||
/* A keyval/evbuf to store response headers and body.
|
/* A keyval/evbuf to store response headers and body.
|
||||||
* Can be set to NULL to ignore that part of the response.
|
* Can be set to NULL to ignore that part of the response.
|
||||||
*/
|
*/
|
||||||
struct keyval *headers;
|
struct keyval *input_headers;
|
||||||
struct evbuffer *body;
|
struct evbuffer *input_body;
|
||||||
|
|
||||||
/* Cut the connection after the headers have been received
|
/* Cut the connection after the headers have been received
|
||||||
* Used for getting Shoutcast/ICY headers for old versions of libav/ffmpeg
|
* Used for getting Shoutcast/ICY headers for old versions of libav/ffmpeg
|
||||||
|
@ -47,15 +52,27 @@ struct http_icy_metadata
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Generic HTTP client. No support for https.
|
/* 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
|
||||||
|
* or better, which is still a bit too new to be in the major distros.
|
||||||
*
|
*
|
||||||
* @param ctx HTTP request params, see above
|
* @param ctx HTTP request params, see above
|
||||||
* @return 0 if successful, -1 if an error occurred
|
* @return 0 if successful, -1 if an error occurred (e.g. no libcurl)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
http_client_request(struct http_client_ctx *ctx);
|
http_client_request(struct http_client_ctx *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/* Converts the keyval dictionary to a application/x-www-form-urlencoded string.
|
||||||
|
* The values will be uri_encoded. Example output: "key1=foo%20bar&key2=123".
|
||||||
|
*
|
||||||
|
* @param kv is the struct containing the parameters
|
||||||
|
* @return encoded string if succesful, NULL if an error occurred
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
http_form_urlencode(struct keyval *kv);
|
||||||
|
|
||||||
|
|
||||||
/* Returns a newly allocated string with the first stream in the m3u given in
|
/* Returns a newly allocated string with the first stream in the m3u given in
|
||||||
* url. If url is not a m3u, the string will be a copy of url.
|
* url. If url is not a m3u, the string will be a copy of url.
|
||||||
*
|
*
|
||||||
|
|
150
src/lastfm.c
150
src/lastfm.c
|
@ -39,14 +39,7 @@
|
||||||
#include "lastfm.h"
|
#include "lastfm.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
struct https_client_ctx
|
|
||||||
{
|
|
||||||
const char *url;
|
|
||||||
const char *body;
|
|
||||||
struct evbuffer *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// LastFM becomes disabled if we get a scrobble, try initialising session,
|
// LastFM becomes disabled if we get a scrobble, try initialising session,
|
||||||
// but can't (probably no session key in db because user does not use LastFM)
|
// but can't (probably no session key in db because user does not use LastFM)
|
||||||
|
@ -172,51 +165,6 @@ credentials_read(char *path, char **username, char **password)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Converts parameters to a string in application/x-www-form-urlencoded format */
|
|
||||||
static int
|
|
||||||
body_print(char **body, struct keyval *kv)
|
|
||||||
{
|
|
||||||
struct evbuffer *evbuf;
|
|
||||||
struct onekeyval *okv;
|
|
||||||
char *k;
|
|
||||||
char *v;
|
|
||||||
|
|
||||||
evbuf = evbuffer_new();
|
|
||||||
|
|
||||||
for (okv = kv->head; okv; okv = okv->next)
|
|
||||||
{
|
|
||||||
k = evhttp_encode_uri(okv->name);
|
|
||||||
if (!k)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
v = evhttp_encode_uri(okv->value);
|
|
||||||
if (!v)
|
|
||||||
{
|
|
||||||
free(k);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
evbuffer_add(evbuf, k, strlen(k));
|
|
||||||
evbuffer_add(evbuf, "=", 1);
|
|
||||||
evbuffer_add(evbuf, v, strlen(v));
|
|
||||||
if (okv->next)
|
|
||||||
evbuffer_add(evbuf, "&", 1);
|
|
||||||
|
|
||||||
free(k);
|
|
||||||
free(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
evbuffer_add(evbuf, "\n", 1);
|
|
||||||
|
|
||||||
*body = evbuffer_readln(evbuf, NULL, EVBUFFER_EOL_ANY);
|
|
||||||
|
|
||||||
evbuffer_free(evbuf);
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_LASTFM, "Parameters in request are: %s\n", *body);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Creates an md5 signature of the concatenated parameters and adds it to keyval */
|
/* Creates an md5 signature of the concatenated parameters and adds it to keyval */
|
||||||
static int
|
static int
|
||||||
param_sign(struct keyval *kv)
|
param_sign(struct keyval *kv)
|
||||||
|
@ -288,28 +236,8 @@ mxmlGetOpaque(mxml_node_t *node) /* I - Node to get */
|
||||||
|
|
||||||
/* --------------------------------- MAIN --------------------------------- */
|
/* --------------------------------- MAIN --------------------------------- */
|
||||||
|
|
||||||
static size_t
|
|
||||||
request_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|
||||||
{
|
|
||||||
size_t realsize;
|
|
||||||
struct https_client_ctx *ctx;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
realsize = size * nmemb;
|
|
||||||
ctx = (struct https_client_ctx *)userdata;
|
|
||||||
|
|
||||||
ret = evbuffer_add(ctx->data, ptr, realsize);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Error adding reply from LastFM to data buffer\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return realsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
response_proces(struct https_client_ctx *ctx)
|
response_proces(struct http_client_ctx *ctx)
|
||||||
{
|
{
|
||||||
mxml_node_t *tree;
|
mxml_node_t *tree;
|
||||||
mxml_node_t *s_node;
|
mxml_node_t *s_node;
|
||||||
|
@ -319,9 +247,9 @@ response_proces(struct https_client_ctx *ctx)
|
||||||
char *sk;
|
char *sk;
|
||||||
|
|
||||||
// NULL-terminate the buffer
|
// NULL-terminate the buffer
|
||||||
evbuffer_add(ctx->data, "", 1);
|
evbuffer_add(ctx->input_body, "", 1);
|
||||||
|
|
||||||
body = (char *)evbuffer_pullup(ctx->data, -1);
|
body = (char *)evbuffer_pullup(ctx->input_body, -1);
|
||||||
if (!body || (strlen(body) == 0))
|
if (!body || (strlen(body) == 0))
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Empty response\n");
|
DPRINTF(E_LOG, L_LASTFM, "Empty response\n");
|
||||||
|
@ -380,59 +308,10 @@ response_proces(struct https_client_ctx *ctx)
|
||||||
mxmlDelete(tree);
|
mxmlDelete(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use libcurl to make the request. We could use libevent and avoid the
|
|
||||||
// dependency, but for SSL, libevent needs to be v2.1 or better, which is still
|
|
||||||
// a bit too new to be in the major distros
|
|
||||||
static int
|
|
||||||
https_client_request(struct https_client_ctx *ctx)
|
|
||||||
{
|
|
||||||
CURL *curl;
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
|
||||||
if (!curl)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Error: Could not get curl handle\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ctx->body);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, ctx->url);
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, request_cb);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
|
|
||||||
|
|
||||||
ctx->data = evbuffer_new();
|
|
||||||
if (!ctx->data)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Could not create evbuffer for LastFM response\n");
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
if (res != CURLE_OK)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Request to %s failed: %s\n", ctx->url, curl_easy_strerror(res));
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
response_proces(ctx);
|
|
||||||
|
|
||||||
evbuffer_free(ctx->data);
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
request_post(char *method, struct keyval *kv, int auth)
|
request_post(char *method, struct keyval *kv, int auth)
|
||||||
{
|
{
|
||||||
struct https_client_ctx ctx;
|
struct http_client_ctx ctx;
|
||||||
char *body;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = keyval_add(kv, "method", method);
|
ret = keyval_add(kv, "method", method);
|
||||||
|
@ -453,18 +332,27 @@ request_post(char *method, struct keyval *kv, int auth)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = body_print(&body, kv);
|
memset(&ctx, 0, sizeof(struct http_client_ctx));
|
||||||
|
|
||||||
|
ctx.output_body = http_form_urlencode(kv);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_LASTFM, "Aborting request, body_print failed\n");
|
DPRINTF(E_LOG, L_LASTFM, "Aborting request, http_form_urlencode failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ctx, 0, sizeof(struct https_client_ctx));
|
|
||||||
ctx.url = auth ? auth_url : api_url;
|
ctx.url = auth ? auth_url : api_url;
|
||||||
ctx.body = body;
|
ctx.input_body = evbuffer_new();
|
||||||
|
|
||||||
ret = https_client_request(&ctx);
|
ret = http_client_request(&ctx);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out_free_ctx;
|
||||||
|
|
||||||
|
response_proces(&ctx);
|
||||||
|
|
||||||
|
out_free_ctx:
|
||||||
|
free(ctx.output_body);
|
||||||
|
evbuffer_free(ctx.input_body);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue