Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support link generation #152

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open

Support link generation #152

wants to merge 11 commits into from

Conversation

Altai-man
Copy link
Member

No description provided.

@@ -58,6 +65,12 @@ module Cro::HTTP::Router {
has Str $.id is required;
}

our $link-plugin is export(:link) = router-plugin-register('link');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it have to be our, given we're exporting it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Cro::HTTP] ===SORRY!=== Error while compiling /home/koto/Work/cro/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router)
[Cro::HTTP] Can't apply trait 'is export' on a my scoped variable. Only our scoped variables are supported.
[Cro::HTTP] at /home/koto/Work/cro/cro-http/lib/Cro/HTTP/Router.pm6 (Cro::HTTP::Router):68

Comment on lines 314 to 315
# my $*CRO-ROUTER-ROUTE-HANDLER = $handler;
# my %*URLS = $handler ~~ DelegateHandler ?? %() !! router-plugin-get-configs($link-plugin);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover commented code

for $includee.handlers() {
@!handlers.push: .copy-adding(:@prefix, :@!body-parsers, :@!body-serializers,
:@!before-matched, :@!after-matched, :@!around, :%!plugin-config);
my $key = ($name-prefix ?? $name-prefix ~ '.' !! '') ~ ($_.name // '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just be .name here, although I wonder if we really need a key if there is no .name?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot, here we check if names from our includes (optionally prefixed) are conflicting with each other and with what we have, the checking is bogus if we omit the prefix.

@!handlers.push: .copy-adding(:@prefix, :@!body-parsers, :@!body-serializers,
:@!before-matched, :@!after-matched, :@!around, :%!plugin-config);
my $key = ($name-prefix ?? $name-prefix ~ '.' !! '') ~ ($_.name // '');
if $name-prefix && $key && (%urls{$key}:exists) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it matter if we have a $name-prefix here? A conflict of route names in a route block that doesn't itself have a name is still a problem?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need it because if the include route ... is anonymous, then we don't have access to its inner names and we don't need to check it for conflicts. Added a comment.

my $outer-handler = .copy-adding(:@prefix, :@!body-parsers, :@!body-serializers,
:@!before-matched, :@!after-matched, :@!around, :%!plugin-config, :$name-prefix, :from-include);
if $outer-handler.name {
my $link-config = $outer-handler.get-innermost-plugin-configs($link-plugin)[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know that the outer handler will always have a config set up?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we have a call to generate-urls before this loop and it adds the link plugin state unconditionally.

}
@options.push: |$links.link-generators.keys;
}
warn "Called the make-link subroutine with $route-name but no such route defined, options are: @options.join('/')";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why warning rather than error?

Copy link
Member Author

@Altai-man Altai-man Aug 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't consider a typo in an url name, which is easy to fix, as something which should crash the whole application.
A working page with just one URL being bogus with a warning for the dev >>> the whole application crashing.

}

{
my $*CRO-ROOT-URL = 'https://foobar.com';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I think we should probably do this by looking at the Host header of the HTTP request...though maybe a fallback is useful too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea, I was piggybacking the test written by @vendethiel here.
The logic should probably be dynamic var // host header value?


test-route-urls route :name<main>, {
get :name<home>, -> {
is make-link('main.home'), '/', 'Basic call of a generator by a short name is correct';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think I'd call this a qualified name, not a short name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

}
}, X::Cro::HTTP::Router::DuplicateLinkName, message => "Conflicting link name: main.home";

# XXX the test intention is bogus?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably yes; at the very least, if we do build a qualified table, it's a separate thing from the unqualified one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it.


test-route-urls route {
get -> {
say make-link('hello', 'world');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug output in test

vendethiel and others added 8 commits November 10, 2021 16:22
Resolve issues we had due to information loss at handlers being
flattened after inclusion, make tests pass again as the conflict
detection is more strict and at the same time smart now.
Here we do three things:
* Before that, URLs constructed for a route had no idea they can be used
  in some outer route block, so they generated `/foo` instead of `/included-prefix/foo`.
  To overcome this, we add an url-prefix attribute when we include a handler we rewrite
  it to an appropriate value.
* Before that, we suffered at referencing the correct names due to route flattening.
  Inner anonymous routes had their handlers not present in the outermost hash,
  and given the hash was implemented as an attribute on the route set, they were
  in fact unable to refer to proper names.
  To overcome this, instaed of using an attribute we rely on the plugin system
  which allows us to separately store the data of inner route blocks.
* This commit also adapts tests to accommodate to removal of the urls attribute
  available before. There is now a fallback method, though it's possible it will
  be removed as well in next commits due to its redundancy.
@jnthn
Copy link
Member

jnthn commented Nov 10, 2021

Doing some testing. Some findings:

my $application = route {
    get :name<home>, -> {
        content 'text/plain', join "\n",
            # Fine
            abs-link('home'),
            abs-link('lit'),
            abs-link('qs', 'tools', query => 'abc?!'),
            abs-link('qs', 'tools'),
            # Fails to % encode the space
            abs-link('segs', 42, 'foo bar.jpg'),
            # Should not consider `is cookie` and `is header`
            abs-link('noqs'),
            '';
    }

    get :name<lit>, -> 'foo', 'bar' { }

    get :name<segs>, -> 'product', $id, 'docs', $file { }

    get :name<qs>, -> 'search', $category, :$query {}

    get :name<noqs>, -> 'baz', :$foo! is cookie, :$bar! is header {}
}

@jnthn
Copy link
Member

jnthn commented Nov 10, 2021

If I change the above example to:

route :name<root>, {

Then all of the examples stop working, complaining that they want the qualified name, however qualification should be optional.

@jnthn
Copy link
Member

jnthn commented Nov 10, 2021

Also expanded with some non-working ones for included routes:

my $application = route {
    get :name<home>, -> {
        content 'text/plain', join "\n",
            # Fine
            abs-link('home'),
            abs-link('lit'),
            abs-link('qs', 'tools', query => 'abc?!'),
            abs-link('qs', 'tools'),
            # Fails to % encode the space
            abs-link('segs', 42, 'foo bar.jpg'),
            # Should not consider `is cookie` and `is header`
#            abs-link('noqs'),
            # These don't work (routes not found)           
            abs-link('blog.home'),
            abs-link('blog.post', 42),
            '';
    }       
    
    get :name<lit>, -> 'foo', 'bar' { }
    
    get :name<segs>, -> 'product', $id, 'docs', $file { }
    
    get :name<qs>, -> 'search', $category, :$query {}
    
    get :name<noqs>, -> 'baz', :$foo! is cookie, :$bar! is header {}
    
    include 'blog' => route :name<blog>, {
        get :name<home>, -> {}
        get :name<post>, -> 'post', $id {}
    }
}

Comment on lines +38 to +39
next if $param ~~ Cro::HTTP::Router::Header;
next if $param ~~ Cro::HTTP::Router::Cookie;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, right, we should do also the same if it's Cro::HTTP::Router::Auth too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, and if the parameter type does Cro::HTTP::Auth also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants