【问题标题】:How can I get the path info of a top level url using Perl?如何使用 Perl 获取顶级 url 的路径信息?
【发布时间】:2011-11-13 13:49:31
【问题描述】:

我正在努力实现的目标

给定一个顶级 URL,例如 http://www.myapp.com/

如果有人要求:

http://www.myapp.com/questions/id/1

我想获取“questions/id/1”部分并将其传递给适当的 Perl 脚本以检索所需的资源。

我的成就

目前我知道如果 url 中有一个额外的级别怎么做,像这样:

http://www.myapp.com/model/questions/id/1

其中“model”只是一个典型的 Perl CGI 脚本,但它没有“.pl”扩展名,Apache perl 处理程序被配置为处理这个,“questions/id/1”部分被解释为路径信息(通过 CGI->path_info())传递给“模型”。

这个想法来自 Andrew Hanenkamp 在 onlamp.com 上关于该主题的文章: Developing RESTful Web Services in Perl

还有什么问题

但是,这种方法不适用于顶级 url,因为没有地方放置“模型”或任何调用的处理程序。我尝试在配置中设置默认文档设置,以便 http://www.myapp.com/ 默认为 http://www.myapp.com/modle

所以输入http://www.myapp.com/questions/id/1 被处理为http://www.myapp.com/model/questions/id/1

但是,Apache 认为这是一个 404 错误。

我怎样才能做到这一点?这甚至是 Perl 的工作还是在 Apache 配置级别更好地处理,或者可能利用一些 Apache API 来捕获 404 错误并从那里提取“/questions/id/1”部分?我不知道。也许这里有人知道。 ;-)

注意:很抱歉以冗长的措辞和迂回的方式提出这个问题。我不太确定引出主题答案所需的术语是什么。在之前在这里和其他地方提出这个问题时提到一个以 R 开头并以 T 结尾的四个字母的单词,导致了关于所说的字母单词的性质以及使用某些框架或其他框架的好意但无益的建议的激烈讨论。我只是想知道这些框架是如何实现这个特性的,我想在 Perl 中实现一个来学习如何去做。

更新: 建议的答案之一使我尝试了 mod_rewrite。作品。但是,为每个映射手动设置 Apache 的 conf 是相当不切实际的。进一步的搜索让我找到了 O'Reilly 的书“Practical mod_perl”。在其中,Bekman 和 Cholet 写了关于通过 Apache CPAN 包以编程方式访问 mod_rewrite 以设置重写。 Appendix 10 : "mod_rewrite in Perl" 现在写一些代码来测试这本书的想法。同时,如果有更好的方法可以做到这一点,请分享。

结论

在对两个 uri 路由/调度程序(或 Whatchamacallit)脚本进行原型设计后,一个依赖 mod_rewrite 调用它,另一个依赖 ErrorDocument;我得出的结论是 mod_rewrite 是实现这一点的正确方法。

ErrorDocument 方法是错误的,因为它不保留来自重定向页面的 POST 数据。 向http://www.myapp.com/questions 发送 POST 请求以创建新资源是不可能的,因为 ErrorDocument 调用的自定义错误处理程序脚本无法使用 POST 数据。此外,由于定义的每个请求都不会访问物理文件,因此 Apache 的错误日志将充满 spurios 404 file not found 错误。这可能是一个巨大的问题,即服务器的交易量很高。感谢大家为我指明正确的方向。现在我的好奇心得到了满足。

【问题讨论】:

  • 如果有人认为问题的措辞不正确,请提出更改建议。我对要使用的正确术语感到困惑。谢谢。
  • 你可以在标题中添加“CGI”——“使用 Perl”有点模糊!
  • 您的两个答案(yko,evil otto)都是完成此任务的好方法。 :-) 但是,在所有条件相同的情况下,我现在倾向于重写,因为我认为为了重新路由而预期会发生错误是一种美学上不那么吸引人的方法。在决定选择哪个答案之前,让社区对这些不同的方法进行投票。

标签: perl apache cgi url-routing


【解决方案1】:

您可以在.htaccess 文件或Apache 配置文件中定义重写规则。 详情请见mod_rewrite

在您的情况下,.htaccess 文件可能如下所示:

AddHandler cgi-script .cgi
Options +ExecCGI

RewriteEngine on

RewriteRule ^(questions/id/.*)$ model.cgi/$1 [L]

如果您只需要处理 /question/id/ 请求,这应该可以工作。但是您可能希望通过您的 Perl 应用程序处理所有请求。所以实际上将所有请求传递给您的应用程序可能是个好主意。比如:

RewriteRule ^(.*)$ app.cgi/$1 [L]

并让您的应用程序调度请求比。 除了...总是有一些例外。您需要让 Apache 为您提供静态文件。而且您需要 Apache 不要将您的应用程序文件(可执行文件和配置)作为静态文件提供。因此,大多数现代 Perl 框架将静态存储在单独的目录中,例如“public”。所以你把你所有的图片、css、js 等放在 /public 中,并按照以下方式配置 Apache:

 RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
 RewriteRule ^(.*) public/$1 [L]

 RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
 RewriteRule ^(.*) myapp.cgi [L] 

这个例子取自Mojolicious documentation

现在,如果用户请求“公共”中存在的内容,Apache 会向用户发送静态文件,并将所有其他请求重定向到您的应用。

在您的应用中,您需要向某些操作发送一些请求。实际上,您需要一个可以为您完成这项工作的模块。由 Viacheslav Tykhanovskyi 编写的 Routes::Tiny(也可在 CPAN 上找到)是一个不错的选择。

毕竟,如果您想知道框架是如何工作的,为什么不深入研究其中之一呢? Mojolicious 和 Dancer 太大了,但你可能会考虑一些更小的东西,比如Lamework,它通过现在成为标准的 PSGI 协议工作。

【讨论】:

  • 谢谢。虽然这不是完全正确的答案,但它让我更接近解决方案。
  • @GeneQ,我更新了我的答案。但是,如果您想知道框架是如何工作的,您真的需要深入了解框架。
【解决方案2】:

我强烈建议使用 Web 开发框架。这将需要一些学习,但是当您完成时,您会意识到您当前的方法远非理想。有许多简单的框架可以让你快速启动和运行。我建议使用 Dancer (www.perldancer.org)。在 Dancer 中,设置路线就像下面的示例一样简单。

get '/' => sub { '你好世界!' }

顺便说一句,您不太可能想要使用 CGI。 CGI 通常性能很差,基本上已经失效。我建议你研究一下 FastCGI 和 PSGI,它们都在 Apache 中可用。

【讨论】:

  • 我正在学习编写框架。我想了解他们如何在内部工作。 ;-)
【解决方案3】:

您可以捕获 404 错误并使用 cgi 脚本进行处理。在您的顶级 .htaccess 文件 (docroot/.htaccess) 中:

ErrorDocument 404 /cgi/my-script.sh

然后在您的处理程序脚本 (my-script.sh) 中,原始路径将作为环境变量 REDIRECT_URL 传递。但请确保您的处理程序脚本通过添加 Status: 200 OK 标头正确设置 HTTP 状态。这是一个示例 cgi 脚本 (/cgi/my-script.sh):

#!/bin/sh

echo Status: 200 OK
echo Content-type: text/plain
echo
echo Your url was $REDIRECT_URL

(我不推荐使用 bourne shell 编写 cgi 脚本,但它说明了方法)。

您也可以将 ErrorDocument 设置放在您的 httpd.conf 文件中,但是任何更改都需要重新启动服务器;将它放在 .htaccess 中可以更轻松地在运行时进行调整。

关于自定义错误处理的 Apache 参考:http://httpd.apache.org/docs/2.1/custom-error.html

如果您使用 mod_perl,将其设置为 perl 处理程序会更容易和更简洁(更不用说性能更好了);再次在顶级 .htaccess 文件(或 httpd.conf)中:

SetHandler perl-script
PerlHandler MyThing::HandlerPackage

其中MyThing::HandlerPackage 是定义适当handler 子的perl 模块。

【讨论】:

  • 啊,原来如此。那是我想不通的事情;如何将脚本挂接到 404 错误。
猜你喜欢
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
  • 2020-02-14
  • 1970-01-01
  • 2020-11-18
  • 2011-07-30
  • 1970-01-01
相关资源
最近更新 更多