pascal 动态网页
Without getting too technical, I would define a Pascal Server Page (PSP) as a dynamic web page containing embedded Pascal Script (PS) code.  When a web request is made, the PS code needs to be executed (interpreted) in the server side and outputted into the proper format (HTML, XML, JSON, text, etc). A PSP is commonly stored as a text file in the Web Server and it could be a mixture of PS code plus any other static content.   
This is an example of PSP:    
Collapse | Copy Code    
<html>    
  <head>    
    <title>This is a Pascal Server Page</title>    
  </head>    
  <body>    
    <% begin    
         Write('Hello World');    
       end.    
    %>    
    <p>I am going to use Pascal Script to write a few numbers...</p>    
    <% var    
         i: Integer;    
       begin    
         for i:=1 to 10 do    
           Writeln(i);  
       end.    
    %>     
  </body>    
</html>     
The code above is an HTML armature containing some PS code. The PS code has been isolated within the “<%” and “%>” tokens. The PS code is executed in the server and the output (if any) is embedded into the HTML template.    
So, if a browser asks for the page above, it will actually get plain HTML code as the one below:    
Collapse | Copy Code    
<html>    
  <head>    
    <title>This is a Pascal Server Page</title>    
  </head>  
  <body>    
    Hello World    
    <p>I am going to use Pascal Script to write a few numbers...</p>    
    1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>    
  </body>    
</html>     
This is all good. The only problem is that the PS code is not going to be magically executed. We need a server side component to do the PS interpretation.    
I have seen a couple of intents to build such server side component in the Internet. Anyhow, I bring you my own proposal: create a Web Broker application with Pascal Scripting capabilities. To provide the Web Broker application with the scripting capabilities, I will use Pascal Script from RemObjects. You need to download and install Pascal Script if you want to try my code.    
The workflow goes as follows:    
1.The Web Broker application receives a Web Request.    
2.The Web Broker application finds the corresponding Pascal Server Page and loads its content to a buffer variable.    
3.The content of the buffer variable is parsed in order to find the PS tokens (I will use RegEx to do the parsing).     
4.Each PS block is compiled to bytecode and then executed in the server. (I will use the Pascal Script library from RemObjects for this purpose).     
5.The output generated from the execution of each PS block replaces its corresponding “<%......%>” block.    
6.The Web Broker app serves the response. 
I developed a VCL standalone Web Broker application as a proof of concept (it could be an ISAPI DLL as well). See it in action in the following video: http://www.youtube.com/embed/NMBn6BjNEW0.
That application is just a prototype. I really believe that we could build a robust server side component to leverage enterprise Pascal Server Pages. I used Web Broker in this example, but we could also build Apache Modules with Free Pascal.
I am posting below the code of the TWebModule1 class, which is the core of the Web Broker app. The full source code and executable can be downloaded here. (the code was compiled with Delphi XE2). Note that the code is somewhat messy; this was taken directly from my sandbox. Ah, I copy-pasted (and adjusted) the Pascal Script routines from this example: Introduction to Pascal Script.   
 Collapse | Copy Code    
unit WebModuleUnit1; 
interface
uses System.SysUtils, System.Classes, Web.HTTPApp,   
     RegularExpressions; 
type   
  TWebModule1 = class(TWebModule)    
    procedure WebModule1DefaultHandlerAction(Sender: TObject;    
      Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);    
  private    
    { Private declarations }    
  public    
    { Public declarations }    
    function LoadStrFromFile(aFilename: string): string;    
    function ProducePage(aContent: string): string;    
    function ExecPascalScript(const Match: TMatch): string;    
    function CompileScript(Script: AnsiString; out Bytecode, Messages: AnsiString): Boolean;    
    function RunCompiledScript(Bytecode: AnsiString; out RuntimeErrors: AnsiString): Boolean;    
  end; 
var   
  WebModuleClass: TComponentClass = TWebModule1; 
  //ScriptOutput is not thread safe.   
  //ScriptOutput is a global variable.    
  //We should avoid global variables.    
  //TODO: Find a better way to store the script output    
  ScriptOutput: string; 
implementation
uses   
  uPSCompiler, uPSRuntime; 
{$R *.dfm}
procedure Write(P1: Variant);   
begin    
  //This try...except is ugly.    
  //TODO: Use a conditional checking instead    
  try    
    ScriptOutput:= ScriptOutput + String(P1);    
  except    
    ScriptOutput:= '';    
  end;    
end; 
procedure Writeln(P1: Variant);   
begin    
  Write(P1);    
  ScriptOutput:= ScriptOutput + '</br>';    
end; 
function TWebModule1.LoadStrFromFile(aFilename: string): string;   
begin    
  Result:= '';    
  if not FileExists(aFilename) then Exit; 
  with TStringStream.Create do   
  try    
    LoadFromFile(aFilename);    
    Result:= DataString;    
  finally    
    Free;    
  end;    
end; 
function TWebModule1.ProducePage(aContent: string): string;   
var    
  RegEx: TRegEx;    
begin    
  ScriptOutput:= '';    
  aContent:= StringReplace(aContent, #13#10, '', [rfReplaceAll]);    
  RegEx.Create('\<\%(.)*?\%\>');    
  Result:= regex.Replace(aContent, ExecPascalScript);    
end; 
function TWebModule1.ExecPascalScript(const Match: TMatch): string;   
var    
  Bytecode,    
  Messages,    
  RuntimeErrors: AnsiString;    
  PS: string;    
begin    
  Result:= '';    
  Bytecode:= '';    
  ScriptOutput:= '';    
  PS:= Match.Value;    
  PS:= StringReplace(PS, '<%', '', []);    
  PS:= StringReplace(PS, '%>', '', []);    
  if CompileScript(PS, Bytecode, Messages) then    
    if RunCompiledScript(Bytecode, RuntimeErrors) then    
      Result:= ScriptOutput;    
end; 
function ExtendCompiler(Compiler: TPSPascalCompiler; const Name: AnsiString): Boolean;   
begin    
  Result := True;    
  try    
    Compiler.AddDelphiFunction('procedure Writeln(P1: Variant);');    
    Compiler.AddDelphiFunction('procedure Write(P1: Variant);');    
  except    
    Result := False; // will halt compilation    
  end;    
end; 
function TWebModule1.CompileScript(Script: AnsiString; out Bytecode, Messages: AnsiString): Boolean;   
var    
  Compiler: TPSPascalCompiler;    
  i: Integer;    
begin    
  Bytecode:= '';    
  Messages:= ''; 
  Compiler:= TPSPascalCompiler.Create;   
  Compiler.OnUses:= ExtendCompiler;    
  try    
    Result:= Compiler.Compile(Script) and Compiler.GetOutput(Bytecode);    
    for i:= 0 to Compiler.MsgCount - 1 do    
      if Length(Messages) = 0 then    
        Messages:= Compiler.Msg[i].MessageToString    
      else    
        Messages:= Messages + #13#10 + Compiler.Msg[i].MessageToString;    
  finally    
    Compiler.Free;    
  end;    
end; 
procedure ExtendRuntime(Runtime: TPSExec; ClassImporter: TPSRuntimeClassImporter);   
begin    
  Runtime.RegisterDelphiMethod(nil, @Writeln, 'Writeln', cdRegister);    
  Runtime.RegisterDelphiMethod(nil, @Write, 'Write', cdRegister);    
end; 
function TWebModule1.RunCompiledScript(Bytecode: AnsiString; out RuntimeErrors: AnsiString): Boolean;   
var    
  Runtime: TPSExec;    
  ClassImporter: TPSRuntimeClassImporter;    
begin    
  Runtime:= TPSExec.Create;    
  ClassImporter:= TPSRuntimeClassImporter.CreateAndRegister(Runtime, false);    
  try    
    ExtendRuntime(Runtime, ClassImporter);    
    Result:= Runtime.LoadData(Bytecode)    
          and Runtime.RunScript    
          and (Runtime.ExceptionCode = erNoError);    
    if not Result then    
      RuntimeErrors:=  PSErrorToString(Runtime.LastEx, '');    
  finally    
    ClassImporter.Free;    
    Runtime.Free;    
  end;    
end; 
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;   
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);    
var    
  HTMLSource,    
  HTMLPascalScriptEmbedded: string;    
begin    
  //Set up HTMLSource at your convenience    
  HTMLSource:= GetCurrentDir + '\testPage.htm';    
  HTMLPascalScriptEmbedded:= LoadStrFromFile(HTMLSource);    
  Response.Content:= ProducePage(HTMLPascalScriptEmbedded);    
end; 
end.
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号