PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label raku. Show all posts
Showing posts with label raku. Show all posts

Friday, November 25, 2022

[FIXED] How does Raku decide which version of a module gets loaded?

 November 25, 2022     api-versioning, module, package, raku, versioning     No comments   

Issue

When I do use Foo:ver<1.0>; it loads version 1.0 of module Foo. But what happens when I do use Foo;?


Solution

TL;DR: When given no specific version a default Raku install will load the latest version from the first CompUnit::Repository it encounters that matches any version of that module (and not neccesarily the highest version out of all CompUnit::Repository).


It is possible to create and load a non-core CompUnit::Repository that itself would only load random versions of a module unless otherwise specified. This answer does not apply to these and will focus on how the various core CompUnit::Repository behave and is specced.

The first thing that determines what module will be loaded is which CompUnit::Repository matches the requested identity first. The default repository chain will look something like this:

# EXAMPLE 1

$ raku -e '.say for $*REPO.repo-chain'
inst#/home/ugexe/.raku
inst#/home/ugexe/raku/install/share/perl6/site
inst#/home/ugexe/raku/install/share/perl6/vendor
inst#/home/ugexe/raku/install/share/perl6

The inst# prefix tells us this is a CompUnit::Repository::Installation. This is relevant because such a repo can contain multiple distributions -- including multiple versions of the same distribution -- which is not true of the single-distribution CompUnit::Repository::FileSystem used for -I. or -Ilib (which are really -Ifile#/home/ugexe/repos/Foo and -Ifile#/home/ugexe/repos/Foo/lib).

# EXAMPLE 2

$ raku -I. -e '.say for $*REPO.repo-chain'
file#/home/ugexe/repos/Foo
inst#/home/ugexe/.raku
inst#/home/ugexe/raku/install/share/perl6/site
inst#/home/ugexe/raku/install/share/perl6/vendor
inst#/home/ugexe/raku/install/share/perl6

Lets assume the following:

  • file#/home/ugexe/repos/Foo contains Foo:ver<0.5>

  • inst#/home/ugexe/.raku contains Foo:ver<0.1> and Foo:ver<1.0>

  • inst#/home/ugexe/.raku contains Foo:ver<2.0> and Foo:ver<0.1>

use Foo; will load:

  • EXAMPLE 1 - Foo:ver<1.0> from inst#/home/ugexe/.raku

  • EXAMPLE 2 - Foo:ver<0.5> from file#/home/ugexe/repos/Foo

Even though the highest version out of all the repositories is Foo:ver<2.0> the first repository in the chain that matches any version of Foo (i.e. use Foo) wins, so Foo:ver<2.0> is never chosen. You might guess this makes "highest version" the second thing that determines which version of a module gets loaded, but its really the 4th! However I've mentioned it here because for typical usage this is sufficient enough.


The 2nd thing that determines which version of a module get loaded is the api field. This essentially is another version field that, when combined with the version itself, gives a basic way of pinning major versions.

Lets assume the following:

  • file#/home/ugexe/repos/Foo contains Foo:api<0>:ver<0.5>

  • inst#/home/ugexe/.raku contains Foo:api<1>:ver<0.1> and Foo:api<0>:ver<1.0>

use Foo; will load:

  • EXAMPLE 1 - Foo:api<1>:ver<0.1> from inst#/home/ugexe/.raku

  • EXAMPLE 2 - Foo:api<0>:ver<0.5> from file#/home/ugexe/repos/Foo

Even though in EXAMPLE 1 the highest version is Foo:api<0>:ver<1.0>, the highest api version is Foo:api<1>:ver<0.1> and thus is chosen.


The 3rd thing that determines which version of a module gets loaded is the auth field. Unlike api and ver it does not imply any sorting. And also unlike api and ver field you probably shouldn't be using it in your e.g. use Foo -- it is policy focused and will serve to be a power-tool/escape hatch most developers should hopefully never have to worry about (ab)using.

Lets assume the following:

  • file#/home/ugexe/repos/Foo contains Foo:auth<github:ugexe>:ver<0.5>

  • inst#/home/ugexe/.raku contains Foo:ver<0.1> and Foo:auth<github:ugexe>:ver<1.0>

use Foo; will load:

  • EXAMPLE 1 - Foo:auth<github:ugexe>:ver<1.0> from inst#/home/ugexe/.raku

  • EXAMPLE 2 - Foo:auth<github:ugexe>:ver<0.5> from file#/home/ugexe/repos/Foo

In both examples use Foo; is the same as use Foo:auth(*):ver(*), so even though one of the repo assumptions contains a module with no auth this does not mean it is an exact match for use Foo;. Instead the :auth(*) includes any auth value as a match (effectively meaning auth is ignored altogether).


For more examples the spec tests are a good source



Answered By - ugexe
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Tuesday, September 20, 2022

[FIXED] How to get the Host or :authority header in Cro when using HTTP/2

 September 20, 2022     cro, http2, raku, request-headers, virtualhost     No comments   

Issue

When using Cro with HTTP1.1 I can access the requested Host via both the host method request.uri.host in Cro::Uri as well as the Host or :authority header sent by the browser via the request.header method in Cro::HTTP::Request.

However, when I use HTTP/2, none of these work. The Uri object only contains the schema and the path.

I'm using an official certificate with a wildcard for subdomains and running this locally by adding these subdomains to my hosts file. Chrome DevTools says it has sent the :authority request header under HTTP/2 and Firefox Developer Tools says it has sent the Host request header under HTTP/2. However if I write the headers to a log like below, I see several headers, but not the Host or :authority header.

sub routes() is export {
  route {
    get -> {
      my $log = "/data/myapp/logs/cro.log";
      my $fh = open $log, :w;
      my $host = request.uri.host;
      $fh.say( "Host with host method: " ~ $host );
      $host = request.header('Host');
      $fh.say( "Host: " ~ $host );
      $host = request.header(':authority');
      $fh.say(":authority: " ~ $host );
      $fh.say( "Request headers:" );
      for request.headers {
        $fh.say( "{.name}: {.value}" );
      }
      $fh.close;
      content 'text/html', "<h1> MyApp </h1><p>Running";
    }
  }
}

I'm aware that HTTP/2 uses Server Name Indication and that the host name is sent as part of the TLS negotiation. On the other hand this is also part of the Cro modules (Cro::TLS) and the headers are sent by the browser nonetheless.

So how to get the host under HTTP/2?


Solution

This appears to be a plain bug (unrelated to ones named by Raiph).

I wrote a patch and sent a PR (https://github.com/croservices/cro-http/pull/104), with it merged you can update your Cro::HTTP distribution and both ways you specified (request.uri construction or asking for header('Host')) will work.



Answered By - Takao
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Wednesday, June 29, 2022

[FIXED] What counts as a newline for Raku *source* files?

 June 29, 2022     comments, newline, raku, rakudo, unicode     No comments   

Issue

I was somewhat surprised to observe that the following code

# comment 
say 1;
# comment 
say 2;
# comment say 3;
# comment say 4;

prints 1, 2, 3, and 4.

Here are the relevant characters after "# comment":

say "

".uninames.raku;
# OUTPUT: «("PARAGRAPH SEPARATOR", "LINE SEPARATOR", "<control-000B>", "<control-000C>").Seq»

Note that many/all of these characters are invisible in most fonts. At least with my editor, none cause the following text to be printed on a new line. And at least one (<control-000C>, aka Form Feed, sometimes printed as ^L) is in fairly wide use in Vim/Emacs as a section separator.

This raises a few questions:

  1. Is this intentional, or a bug?
  2. If intentional, what's the use-case (other than winning obfuscated code contests!)
  3. Is it just these 4 characters, or are there others? (I found these because they share the mandatory break Unicode property. Does that property (or some other Unicode property?) govern what Raku considers as a newline?)
  4. Just, really, wow.

(I realize #4 is not technically a question, but I feel it needed to be said).


Solution

Raku's syntax is defined as a Raku grammar. The rule for parsing such a comment is:

token comment:sym<#> {
   '#' {} \N*
}

That is, it eats everything after the # that is not a newline character. As with all built-in character classes in Raku, \n and its negation are Unicode-aware. The language design docs state:

\n matches a logical (platform independent) newline, not just \x0a. See TR18 section 1.6 for a list of logical newlines.

Which is a reference to the Unicode standard for regular expressions.

I somewhat doubt there was ever a specific language design discussion along the lines of "let's enable all the kinds of newlines in Unicode, it'll be cool!" Rather, the decisions were that Raku should follow the Unicode regex technical report, and that Raku syntax would be defined in terms of a Raku grammar and thus make use of the Unicode-aware character classes. That a range of different newline characters are supported is a consequence of consistently following those principles.



Answered By - Jonathan Worthington
Answer Checked By - Timothy Miller (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing