|  | @@ -684,6 +684,51 @@ int http_open ( struct interface *xfer, struct http_method *method,
 | 
		
	
		
			
			| 684 | 684 |  	return rc;
 | 
		
	
		
			
			| 685 | 685 |  }
 | 
		
	
		
			
			| 686 | 686 |  
 | 
		
	
		
			
			|  | 687 | +/**
 | 
		
	
		
			
			|  | 688 | + * Redirect HTTP transaction
 | 
		
	
		
			
			|  | 689 | + *
 | 
		
	
		
			
			|  | 690 | + * @v http		HTTP transaction
 | 
		
	
		
			
			|  | 691 | + * @v location		New location
 | 
		
	
		
			
			|  | 692 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 693 | + */
 | 
		
	
		
			
			|  | 694 | +static int http_redirect ( struct http_transaction *http,
 | 
		
	
		
			
			|  | 695 | +			   const char *location ) {
 | 
		
	
		
			
			|  | 696 | +	struct uri *location_uri;
 | 
		
	
		
			
			|  | 697 | +	struct uri *resolved_uri;
 | 
		
	
		
			
			|  | 698 | +	int rc;
 | 
		
	
		
			
			|  | 699 | +
 | 
		
	
		
			
			|  | 700 | +	DBGC2 ( http, "HTTP %p redirecting to \"%s\"\n", http, location );
 | 
		
	
		
			
			|  | 701 | +
 | 
		
	
		
			
			|  | 702 | +	/* Parse location URI */
 | 
		
	
		
			
			|  | 703 | +	location_uri = parse_uri ( location );
 | 
		
	
		
			
			|  | 704 | +	if ( ! location_uri ) {
 | 
		
	
		
			
			|  | 705 | +		rc = -ENOMEM;
 | 
		
	
		
			
			|  | 706 | +		goto err_parse_uri;
 | 
		
	
		
			
			|  | 707 | +	}
 | 
		
	
		
			
			|  | 708 | +
 | 
		
	
		
			
			|  | 709 | +	/* Resolve as relative to original URI */
 | 
		
	
		
			
			|  | 710 | +	resolved_uri = resolve_uri ( http->uri, location_uri );
 | 
		
	
		
			
			|  | 711 | +	if ( ! resolved_uri ) {
 | 
		
	
		
			
			|  | 712 | +		rc = -ENOMEM;
 | 
		
	
		
			
			|  | 713 | +		goto err_resolve_uri;
 | 
		
	
		
			
			|  | 714 | +	}
 | 
		
	
		
			
			|  | 715 | +
 | 
		
	
		
			
			|  | 716 | +	/* Redirect to new URI */
 | 
		
	
		
			
			|  | 717 | +	if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI,
 | 
		
	
		
			
			|  | 718 | +				    resolved_uri ) ) != 0 ) {
 | 
		
	
		
			
			|  | 719 | +		DBGC ( http, "HTTP %p could not redirect: %s\n",
 | 
		
	
		
			
			|  | 720 | +		       http, strerror ( rc ) );
 | 
		
	
		
			
			|  | 721 | +		goto err_redirect;
 | 
		
	
		
			
			|  | 722 | +	}
 | 
		
	
		
			
			|  | 723 | +
 | 
		
	
		
			
			|  | 724 | + err_redirect:
 | 
		
	
		
			
			|  | 725 | +	uri_put ( resolved_uri );
 | 
		
	
		
			
			|  | 726 | + err_resolve_uri:
 | 
		
	
		
			
			|  | 727 | +	uri_put ( location_uri );
 | 
		
	
		
			
			|  | 728 | + err_parse_uri:
 | 
		
	
		
			
			|  | 729 | +	return rc;
 | 
		
	
		
			
			|  | 730 | +}
 | 
		
	
		
			
			|  | 731 | +
 | 
		
	
		
			
			| 687 | 732 |  /**
 | 
		
	
		
			
			| 688 | 733 |   * Handle successful transfer completion
 | 
		
	
		
			
			| 689 | 734 |   *
 | 
		
	
	
		
			
			|  | @@ -717,14 +762,8 @@ static int http_transfer_complete ( struct http_transaction *http ) {
 | 
		
	
		
			
			| 717 | 762 |  
 | 
		
	
		
			
			| 718 | 763 |  	/* Perform redirection, if applicable */
 | 
		
	
		
			
			| 719 | 764 |  	if ( ( location = http->response.location ) ) {
 | 
		
	
		
			
			| 720 |  | -		DBGC2 ( http, "HTTP %p redirecting to \"%s\"\n",
 | 
		
	
		
			
			| 721 |  | -			http, location );
 | 
		
	
		
			
			| 722 |  | -		if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING,
 | 
		
	
		
			
			| 723 |  | -					    location ) ) != 0 ) {
 | 
		
	
		
			
			| 724 |  | -			DBGC ( http, "HTTP %p could not redirect: %s\n",
 | 
		
	
		
			
			| 725 |  | -			       http, strerror ( rc ) );
 | 
		
	
		
			
			|  | 765 | +		if ( ( rc = http_redirect ( http, location ) ) != 0 )
 | 
		
	
		
			
			| 726 | 766 |  			return rc;
 | 
		
	
		
			
			| 727 |  | -		}
 | 
		
	
		
			
			| 728 | 767 |  		http_close ( http, 0 );
 | 
		
	
		
			
			| 729 | 768 |  		return 0;
 | 
		
	
		
			
			| 730 | 769 |  	}
 |