From f619ebe9d3343867bc8a8d5e98e6b81e645129e5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 23 Mar 2014 00:29:18 +0100 Subject: [PATCH] add a utility function to detect redirects and handle them Signed-off-by: Felix Fietkau --- uclient-backend.h | 1 + uclient-http.c | 38 ++++++++++++++++++++++++++++++++++++++ uclient.c | 15 ++++++++++----- uclient.h | 1 + 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/uclient-backend.h b/uclient-backend.h index abbfbc6..fdebf26 100644 --- a/uclient-backend.h +++ b/uclient-backend.h @@ -31,5 +31,6 @@ struct uclient_url { void uclient_backend_set_error(struct uclient *cl); void uclient_backend_set_eof(struct uclient *cl); void uclient_backend_reset_state(struct uclient *cl); +struct uclient_url *uclient_get_url(const char *url_str, const char *auth_str); #endif diff --git a/uclient-http.c b/uclient-http.c index b6f28e1..0ce43c2 100644 --- a/uclient-http.c +++ b/uclient-http.c @@ -850,6 +850,44 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len) return len; } +bool uclient_http_redirect(struct uclient *cl) +{ + struct uclient_http *uh = container_of(cl, struct uclient_http, uc); + struct blobmsg_policy location = { + .name = "location", + .type = BLOBMSG_TYPE_STRING, + }; + struct uclient_url *url = cl->url; + struct blob_attr *tb; + + if (cl->backend != &uclient_backend_http) + return false; + + switch (cl->status_code) { + case 301: + case 302: + case 307: + break; + default: + return false; + } + + blobmsg_parse(&location, 1, &tb, blob_data(uh->meta.head), blob_len(uh->meta.head)); + if (!tb) + return false; + + url = uclient_get_url(blobmsg_data(tb), url->auth); + if (!url) + return false; + + free(cl->url); + cl->url = url; + uclient_http_connect(cl); + uclient_http_request_done(cl); + + return true; +} + const struct uclient_backend uclient_backend_http = { .prefix = uclient_http_prefix, diff --git a/uclient.c b/uclient.c index 9453365..e7213a1 100644 --- a/uclient.c +++ b/uclient.c @@ -3,7 +3,8 @@ #include "uclient-utils.h" #include "uclient-backend.h" -static struct uclient_url *uclient_get_url(const char *url_str) +struct uclient_url * __hidden +uclient_get_url(const char *url_str, const char *auth_str) { static const struct uclient_backend *backends[] = { &uclient_backend_http, @@ -13,7 +14,7 @@ static struct uclient_url *uclient_get_url(const char *url_str) const char * const *prefix = NULL; struct uclient_url *url; const char *location; - char *host_buf, *uri_buf, *next; + char *host_buf, *uri_buf, *auth_buf, *next; int i, host_len; for (i = 0; i < ARRAY_SIZE(backends); i++) { @@ -48,7 +49,8 @@ static struct uclient_url *uclient_get_url(const char *url_str) url = calloc_a(sizeof(*url), &host_buf, host_len + 1, - &uri_buf, strlen(location) + 1); + &uri_buf, strlen(location) + 1, + &auth_buf, auth_str ? strlen(auth_str) + 1 : 0); url->backend = backend; url->location = strcpy(uri_buf, location); @@ -66,6 +68,9 @@ static struct uclient_url *uclient_get_url(const char *url_str) url->auth = host_buf; } + if (!url->auth && auth_str) + url->auth = strcpy(auth_buf, auth_str); + /* Literal IPv6 address */ if (*url->host == '[') { url->host++; @@ -94,7 +99,7 @@ struct uclient *uclient_new(const char *url_str, const struct uclient_cb *cb) struct uclient *cl; struct uclient_url *url; - url = uclient_get_url(url_str); + url = uclient_get_url(url_str, NULL); if (!url) return NULL; @@ -115,7 +120,7 @@ int uclient_connect_url(struct uclient *cl, const char *url_str) const struct uclient_backend *backend = cl->backend; if (url_str) { - url = uclient_get_url(url_str); + url = uclient_get_url(url_str, NULL); if (!url) return -1; diff --git a/uclient.h b/uclient.h index f4009e0..e3d168a 100644 --- a/uclient.h +++ b/uclient.h @@ -52,5 +52,6 @@ extern const struct uclient_backend uclient_backend_http; int uclient_http_set_header(struct uclient *cl, const char *name, const char *value); int uclient_http_reset_headers(struct uclient *cl, const char *name, const char *value); int uclient_http_set_request_type(struct uclient *cl, const char *type); +bool uclient_http_redirect(struct uclient *cl); #endif -- 2.11.0