fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-09-09 11:24 am

[dw-free] Helper function to create URLs

[commit: http://hg.dwscoalition.org/dw-free/rev/518b72120000]

http://bugs.dwscoalition.org/show_bug.cgi?id=3017

Add an LJ::create_url helper function, which creates a URL to be printed on
the page, based on the page URL, and carrying over various GET arguments.

Patch by [personal profile] exor674.

Files modified:
  • cgi-bin/weblib.pl
  • t/create-url.t
--------------------------------------------------------------------------------
diff -r 9166db025b2d -r 518b72120000 cgi-bin/weblib.pl
--- a/cgi-bin/weblib.pl	Thu Sep 09 19:16:43 2010 +0800
+++ b/cgi-bin/weblib.pl	Thu Sep 09 19:24:25 2010 +0800
@@ -966,6 +966,61 @@ sub viewing_style_opts {
     }
 
     return \%ret;
+}
+
+=head2 C<< LJ::create_url($path,%opts) >>
+If specified, path must begin with a /
+
+args being a list of arguments to create.
+opts can contain:
+host -- link to different domains
+args -- get arguments to add
+ssl -- use ssl
+fragment -- add fragment identifier
+cur_args -- hashref of current GET arguments to the page
+keep_args -- arguments to keep
+viewing_style -- include viewing style args
+=cut
+
+sub create_url {
+    my ( $path, %opts ) = @_;
+
+    my $r = DW::Request->get;
+    my %out_args = %{ $opts{args} || {} };
+
+    my $host = $opts{host} || $r->header_in("Host");
+    $path ||= $r->uri;
+
+    # Default SSL if SSL is set and we are on the same host, unless we explicitly don't want it
+    $opts{ssl} = $LJ::IS_SSL unless $opts{host} || exists $opts{ssl};
+
+    my $url = ( $opts{ssl} ? "https" : "http" ) . "://$host$path";
+    $url .= "#" . $opts{fragment} if $opts{fragment};
+
+    my $orig_args = $opts{cur_args} || DW::Request->get->get_args;
+
+    # Move over viewing style arguments
+    if( $opts{viewing_style} ) {
+        my $vs_args = LJ::viewing_style_opts( %$orig_args );
+        foreach my $k ( keys %$vs_args ) {
+            $out_args{$k} = $vs_args->{$k} unless exists $out_args{$k};
+        }
+    }
+
+    # Move over arguments that we need to keep
+    foreach my $k ( @{$opts{keep_args}} ) {
+        $out_args{$k} = $orig_args->{$k} if exists $orig_args->{$k} && ! exists $out_args{$k};
+    }
+
+    foreach my $k ( keys %out_args ) {
+        delete $out_args{$k} unless defined $out_args{$k};
+    }
+
+    my $args = encode_url_string( \%out_args );
+
+    $url .= "?$args" if $args;
+
+    return $url;
 }
 
 # <LJFUNC>
diff -r 9166db025b2d -r 518b72120000 t/create-url.t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/t/create-url.t	Thu Sep 09 19:24:25 2010 +0800
@@ -0,0 +1,221 @@
+# -*-perl-*-
+use strict;
+use Test::More tests => 5 * 14; # replace last number with the number of check_req calls
+use lib "$ENV{LJHOME}/cgi-bin";
+
+require 'ljlib.pl';
+use DW::Request::Standard;
+use HTTP::Request;
+
+check_req(
+    "http://www.example.com/",
+    undef, {
+        args => {
+            foo => "bar"
+        },
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    { foo => "bar", },
+);
+
+check_req(
+    "http://www.example.com/?bar=baz",
+    undef, {
+        args => {
+            foo => 'bar',
+        },
+        keep_args => [ 'bar' ],
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    {
+        foo => "bar",
+        bar => "baz",
+    },
+);
+
+check_req(
+    "http://www.example.com/?bar=baz&s2id=5&format=light&style=site",
+    undef, {
+        args => {
+            foo => 'bar',
+        },
+        keep_args => [ 'bar' ],
+        viewing_style => 1
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    {
+        foo => "bar",
+        bar => "baz",
+        s2id => 5,
+        format => "light",
+        style => "site",
+    },
+);
+
+check_req(
+    "http://www.example.com/?bar=baz&s2id=5&format=light&style=site",
+    undef, {
+        args => {
+            foo => 'bar',
+            s2id => undef,
+            bar => "kitten",
+        },
+        keep_args => [ 'bar' ],
+        viewing_style => 1
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    {
+        foo => "bar",
+        bar => "kitten",
+        format => "light",
+        style => "site",
+    },
+);
+
+check_req(
+    "http://www.example.com/?bar=baz&s2id=5&format=light&style=site&some=other&cruft=1",
+    undef, {
+        args => {
+            foo => 'bar',
+            bar => undef,
+            mew => undef,
+        },
+        keep_args => [ 'bar' ],
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    {
+        foo => "bar",
+    },
+);
+
+check_req(
+    "https://www.example.com/",
+    undef, {
+    },
+    { ssl => 1, host => "www.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "https://www.example.com/",
+    undef, {
+        ssl => 0,
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "https://www.example.com/",
+    undef, {
+        ssl => 1,
+    },
+    { ssl => 1, host => "www.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "http://www.example.com/",
+    undef, {
+        ssl => 1,
+    },
+    { ssl => 1, host => "www.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "https://www.example.com/",
+    undef, {
+        host => "foo.example.com",
+    },
+    { ssl => 0, host => "foo.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "https://www.example.com/",
+    undef, {
+        host => "foo.example.com",
+        ssl => 1,
+    },
+    { ssl => 1, host => "foo.example.com", uri=>"/", },
+    {},
+);
+
+check_req(
+    "http://www.example.com/",
+    "/mmm_path", {
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/mmm_path", },
+    {},
+);
+
+check_req(
+    "http://www.example.com/meow",
+    undef, {
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/meow", },
+    {},
+);
+
+check_req(
+    "http://www.example.com/meow",
+    undef, {
+        fragment => "kitten",
+    },
+    { ssl => 0, host => "www.example.com", uri=>"/meow", fragment => "kitten" },
+    {},
+);
+
+sub check_req {
+    my ( $url, $path, $opts, $eopts, $expected ) = @_;
+
+    my $rq = HTTP::Request->new(GET => $url);
+    my ( $https, $host ) = $url =~ m!^(http(?:s)?)://(.+?)/!;
+    $LJ::IS_SSL = ( $https eq 'https' ) ? 1 : 0;
+    $rq->header("Host", $host);
+
+    DW::Request->reset;
+    my $r = DW::Request::Standard->new($rq);
+
+    my $nurl = LJ::create_url( $path, %$opts );
+
+    validate_req($nurl,$eopts,$expected);
+}
+
+sub validate_req {
+    my ( $url, $eopts, $expected ) = @_;
+
+    my ( $https, $host, $blah, $fragment, $blah2 ) = $url =~ m!^(http(?:s)?)://(.+?)/(.*?)((?:#.+?)?)((?:\?.+?)?)$!;
+    my $ssl = ( $https eq 'https' ) ? 1 : 0;
+    my $rq = HTTP::Request->new(GET => $url);
+
+    DW::Request->reset;
+    my $r = DW::Request::Standard->new($rq);
+
+    is( $r->uri, $eopts->{uri}, "uri mismatch" );
+    is( $host, $eopts->{host}, "host mismatch" );
+    is( $ssl, $eopts->{ssl}, "invalid ssl" );
+
+    if ( $fragment ) {
+        $fragment =~ s/^#//;
+    } else {
+        $fragment = undef;
+    }
+
+    is( $fragment, $eopts->{fragment}, "invalid fragment" );
+
+    my $fail = '';
+    my $args = $r->get_args;
+
+    foreach my $k ( keys %$args ) {
+        if ( $args->{$k} ne $expected->{$k} ) {
+            $fail .= "$k ( $args->{$k} != $expected->{$k} ), ";
+        }
+        delete $expected->{$k};
+    }
+
+    $fail .= " -- missing: " . join(",", keys %$expected) if ( %$expected );
+
+    ok( ! $fail, "args mismatch: $fail");
+}
\ No newline at end of file
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org