diff --git a/src/ne_request.c b/src/ne_request.c index bf6c986b..781d77f0 100644 --- a/src/ne_request.c +++ b/src/ne_request.c @@ -762,24 +762,30 @@ static void free_response_headers(ne_request *req) ne_uri *ne_get_response_location(ne_request *req, const char *fragment) { const char *location; - ne_uri dest, base, *ret; + ne_uri dest, base, *ret = NULL; location = get_response_header_hv(req, HH_HV_LOCATION, "location"); if (location == NULL) return NULL; + memset(&base, 0, sizeof base); + memset(&dest, 0, sizeof dest); + + /* Location is a URI-reference (RFC9110ẞ10.2.2) relative to the + * request target URI; determine each of these then resolve. */ + /* Parse the Location header */ if (ne_uri_parse(location, &dest) || !dest.path) { - ne_set_error(req->session, _("Could not parse redirect " + ne_set_error(req->session, _("Could not parse redirect " "destination URL")); - return NULL; + goto fail; } - /* Location is a URI-reference (RFC9110ẞ10.2.2) relative to the - * request target URI; create that base URI: */ - memset(&base, 0, sizeof base); - ne_fill_server_uri(req->session, &base); - base.path = req->target; + if (get_request_target_uri(req, &base)) { + ne_set_error(req->session, _("Could not parse redirect " + "destination URL")); + goto fail; + } ret = ne_malloc(sizeof *ret); ne_uri_resolve(&base, &dest, ret); @@ -789,7 +795,7 @@ ne_uri *ne_get_response_location(ne_request *req, const char *fragment) ret->fragment = ne_strdup(fragment); } - base.path = NULL; /* owned by ne_request object, don't free */ +fail: ne_uri_free(&base); ne_uri_free(&dest); diff --git a/test/redirect.c b/test/redirect.c index 12ccae9d..0a6fa703 100644 --- a/test/redirect.c +++ b/test/redirect.c @@ -144,6 +144,10 @@ static int redirects(void) /* all 3xx should get NE_REDIRECT. */ {PATH, 399, DEST, DEST, NULL}, + /* Handling of various request-target cases. */ + {"*", 307, "/fish#food", "/fish#food", NULL}, + {"ftp://example.com/fish", 307, "/fish#food", "ftp://example.com/fish#food", NULL}, + /* More relative URIs: */ {"/blah", 307, "//example.com:8080/fish#food", "http://example.com:8080/fish#food", NULL}, {"/blah", 307, "#food", "/blah#food", NULL}, diff --git a/test/request.c b/test/request.c index 292fc1a3..8d42c033 100644 --- a/test/request.c +++ b/test/request.c @@ -2468,7 +2468,10 @@ static int targets(void) ONCMP(ts[n].expected, actual, "request target", "URI"); if (actual) ne_free(actual); - if (uri) ne_uri_free(uri); + if (uri) { + ne_uri_free(uri); + ne_free(uri); + } ne_request_destroy(req); ne_session_destroy(sess);