Index: lib/Jifty/Web.pm =================================================================== --- lib/Jifty/Web.pm (revision 5171) +++ lib/Jifty/Web.pm (working copy) @@ -121,12 +121,18 @@ the configuration file. Takes an optional named path which will form the path part of the resulting URL. +If the provided path appears to be a relative path, it is assumed to +be relative to the application's base path, set by the C +configuration. Passing a true value for C makes it absolute +to the server's root, instead of the application's root. + =cut sub url { my $self = shift; my %args = (scheme => undef, path => undef, + absolute => undef, @_); my $uri; @@ -171,6 +177,9 @@ if (defined $args{path}) { my $path = $args{path}; + # Add / in case we have an application path to tak on before + $path =~ s{^/?}{/}; + $path = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $path unless $args{absolute}; # strip off leading '/' because ->canonical provides one $path =~ s{^/}{}; $uri->path_query($path); @@ -628,9 +637,11 @@ return ( 1 ) if $self->force_redirect; + my $current_path = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $self->request->path; + if (!$self->request->is_subrequest and $self->next_page - and ( ( $self->next_page ne $self->request->path ) + and ( ( $self->next_page ne $current_path ) or $self->request->state_variables or $self->state_variables ) ) @@ -674,24 +685,38 @@ If you want to redirect to a page with parameters, pass in a L object. +If the URL to redirect to includes an explicit host, B, and a simple redirect is done instead. + =cut sub redirect { my $self = shift; - my $redir_to = shift || $self->next_page || $self->request->path; + my $redir_to = shift; + $self->log->debug("App root is ".URI->new(Jifty->config->framework('Web')->{BaseURL})->path); + $redir_to = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $redir_to if $redir_to and not ref $redir_to; - + $redir_to ||= $self->next_page; + $redir_to ||= URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $self->request->path; + my $page; - if ( ref $redir_to and $redir_to->isa("Jifty::Web::Form::Clickable")) { $page = $redir_to; } else { $page = Jifty::Web::Form::Clickable->new(); - #We set this after creation to ensure that plugins that massage clickables don't impact us + #We set this after creation to ensure that plugins that + #massage clickables don't impact us. Also, the url is thus + #from the server root, not the application root $page->url($redir_to ); } + # External redirect if it includes a host + if (URI->new($page->complete_url,"http")->host) { + return $self->_redirect($page->complete_url); + } + + carp "Don't include GET parameters in the redirect URL -- use a Jifty::Web::Form::Clickable instead. See L" if $page->url =~ /\?/; my %overrides = ( @_ ); @@ -732,8 +757,14 @@ } my %parameters = ($page->parameters); $request->argument($_ => $parameters{$_}) for keys %parameters; - $request->path($page->url); + # We need to be careful that this path is relative to the + # application root, not the server root + my $app_root = URI->new(Jifty->config->framework('Web')->{BaseURL})->path; + my $url = $page->url; + $url =~ s/^$app_root//; + $request->path($url); + $request->continuation($self->request->continuation); my $cont = Jifty::Continuation->new( request => $request, @@ -1084,8 +1115,10 @@ # is returned. defined $self->call_trigger( 'include_css', @_ ) or return ''; + my $base = URI->new(Jifty->config->framework('Web')->{BaseURL})->path; + $self->out( '' ); + . qq{href="$base/static/css/main.css" />} ); return ''; } Index: lib/Jifty/Action/Redirect.pm =================================================================== --- lib/Jifty/Action/Redirect.pm (revision 5171) +++ lib/Jifty/Action/Redirect.pm (working copy) @@ -45,13 +45,21 @@ =head2 arguments -The only argument to redirect is the C to redirect to. +The main argument is the C to redirect to. +If the C appears to be a relative path, it is assumed to be +relative to the application's base path, set by the C +configuration. Passing a true value for the Cargument makes +it absolute to the server's root. Relative paths, and paths which +contain a full URL, including scheme, are never modified, regardless +of this option. + =cut sub arguments { { url => { constructor => 1 }, + absolute => {}, } } @@ -75,6 +83,9 @@ # Find the URL to redirect to my $page = $self->argument_value('url'); + if ($page =~ m|^/| and not $self->argument_value('absolute')) { + $page = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $page; + } # Set the next page and force the redirect Jifty->web->next_page($page); Index: lib/Jifty/Continuation.pm =================================================================== --- lib/Jifty/Continuation.pm (revision 5171) +++ lib/Jifty/Continuation.pm (working copy) @@ -143,10 +143,12 @@ sub return_path_matches { my $self = shift; my $called_uri = $ENV{'REQUEST_URI'}; - my $request_path = $self->request->path; + # Since REQUEST_URI is relative to the HTTP root, we need to make + # our internal request path relative to that, too. + my $request_path = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $self->request->path; + # XXX TODO: WE should be using URI canonicalization - my $escape; $called_uri =~ s{/+}{/}g; $called_uri = Encode::encode_utf8($called_uri); @@ -213,7 +215,8 @@ if defined $next->parent; # Redirect to right page if we're not there already - Jifty->web->_redirect($next->request->path . "?J:RETURN=" . $next->id); + my $page = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $next->request->path; + Jifty->web->_redirect($page . "?J:RETURN=" . $next->id); return 1; } Index: lib/Jifty/Plugin/CompressedCSSandJS.pm =================================================================== --- lib/Jifty/Plugin/CompressedCSSandJS.pm (revision 5171) +++ lib/Jifty/Plugin/CompressedCSSandJS.pm (working copy) @@ -62,7 +62,7 @@ $self->gzip_enabled( exists $opt{gzip} ? $opt{gzip} : 1); $self->js( $opt{js} ); $self->jsmin( $opt{jsmin} ); - $self->cdn( $opt{cdn} || ''); + $self->cdn( $opt{cdn} || URI->new(Jifty->config->framework('Web')->{BaseURL})->path); Jifty::Web->add_trigger( name => 'include_javascript', Index: lib/Jifty/Dispatcher.pm =================================================================== --- lib/Jifty/Dispatcher.pm (revision 5171) +++ lib/Jifty/Dispatcher.pm (working copy) @@ -1230,7 +1230,8 @@ ); # Redirect with a continuation - Jifty->web->_redirect( "/__jifty/error/mason_internal_error?J:C=" . $c->id ); + my $base = URI->new(Jifty->config->framework('Web')->{BaseURL})->path; + Jifty->web->_redirect( "$base/__jifty/error/mason_internal_error?J:C=" . $c->id ); } elsif ($err) { die $err; } Index: lib/Jifty/Request.pm =================================================================== --- lib/Jifty/Request.pm (revision 5171) +++ lib/Jifty/Request.pm (working copy) @@ -571,8 +571,10 @@ ); # Set us up with the new continuation + my $base = URI->new(Jifty->config->framework('Web')->{BaseURL})->path; Jifty->web->_redirect( - $path + $base + . $path . ( $path =~ /\?/ ? "&" : "?" ) . "J:C=" . $c->id ); } Index: lib/Jifty/Web/Form/Clickable.pm =================================================================== --- lib/Jifty/Web/Form/Clickable.pm (revision 5171) +++ lib/Jifty/Web/Form/Clickable.pm (working copy) @@ -138,6 +138,14 @@ For things that start off as links, give them an html C attribute. +=item absolute + +If the path appears to be a relative path, it is assumed to be +relative to the application's base path, set by the C +configuration. Passing a true value for C makes it absolute +to the server's root. Relative paths, and paths which contain a full +URL, including scheme, are never modified, regardless of this option. + =cut =item Anything from L @@ -164,6 +172,10 @@ $class->call_trigger( 'before_new', \%args ); + if (defined $args{url} and $args{url} =~ m|^/| and not $args{absolute}) { + $args{url} = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $args{url}; + } + $args{render_as_button} = delete $args{as_button}; $args{render_as_link} = delete $args{as_link}; @@ -397,6 +409,7 @@ $parameters{"J:CREATE"} = 1; $parameters{"J:PATH"} = Jifty::Web::Form::Clickable->new( url => $self->url, + absolute => 1, parameters => $self->{parameters}, continuation => undef, )->complete_url; @@ -439,9 +452,10 @@ if ( $self->url ne $root and not $self->returns ) { Jifty::Util->require('Jifty::Action::Redirect'); my $redirect = Jifty::Action::Redirect->new( - arguments => { url => $self->url } ); + arguments => { url => $self->url }, absolute => 1 ); $parameters{ $redirect->register_name } = ref $redirect; $parameters{ $redirect->form_field_name('url') } = $self->url; + $parameters{ $redirect->form_field_name('absolute') } = 1; $parameters{"J:ACTIONS"} = join( '!', @{ $self->submit }, $redirect->moniker ) if $self->submit; Index: lib/Jifty/Web/Form.pm =================================================================== --- lib/Jifty/Web/Form.pm (revision 5171) +++ lib/Jifty/Web/Form.pm (working copy) @@ -36,6 +36,18 @@ Disable B autocomplete for this form. Jifty autocomplete will still work. +=item submit_to + +Sets the URL that the form submits to, by default. + +=item absolute + +If the C appears to be a relative path, it is assumed to be +relative to the application's base path, set by the C +configuration. Passing a true value for C makes it absolute +to the server's root. Relative paths, and paths which contain a full +URL, including scheme, are never modified, regardless of this option. + =back =cut @@ -50,6 +62,7 @@ submit_to => undef, target => undef, disable_autocomplete => undef, + absolute => undef, @_, ); @@ -83,8 +96,13 @@ target => undef, submit_to => undef, disable_autocomplete => undef, + absolute => undef, @_); + if (defined $args{'submit_to'} and $args{'submit_to'} =~ m|^/| and not $args{absolute}) { + $args{'submit_to'} = URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $args{'submit_to'}; + } + $self->actions( {} ) ; $self->printed_actions( {} ) ; $self->name($args{name}); @@ -199,7 +217,10 @@ } } - my $form_start = qq!
submit_to; + $submit_to ||= URI->new(Jifty->config->framework('Web')->{BaseURL})->path . $ENV{PATH_INFO}; + + my $form_start = qq!name; $form_start .= qq! target="@{[ $self->target ]}"! if defined $self->target; $form_start .= qq! autocomplete="off"! if defined $self->disable_autocomplete;