Skip to content

Commit

Permalink
Fix new Location: handling for non-origin-form request-target.
Browse files Browse the repository at this point in the history
* src/ne_request.c (ne_get_response_location): Rewrite to use target
  URI correctly determined from get_request_target_uri, fixing
  non-origin-form cases.

* test/redirect.c (redirects): Test for non-origin-form targets.
  • Loading branch information
notroj committed Aug 19, 2024
1 parent 6ae2cff commit 0d302f8
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
24 changes: 15 additions & 9 deletions src/ne_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions test/redirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
5 changes: 4 additions & 1 deletion test/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 0d302f8

Please sign in to comment.