1 | unit UWebApp;
|
---|
2 |
|
---|
3 | {$mode Delphi}{$H+}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, CustApp, SpecializedList, UWebPage, UHTTPSessionFile,
|
---|
9 | UHTTPServer, Forms, FileUtil;
|
---|
10 |
|
---|
11 | type
|
---|
12 | THTTPServerType = (stCGI, stTCP, stTurboPower);
|
---|
13 |
|
---|
14 | TRegistredPage = class
|
---|
15 | Name: string;
|
---|
16 | Page: TWebPage;
|
---|
17 | end;
|
---|
18 |
|
---|
19 | { TPageList }
|
---|
20 |
|
---|
21 | TPageList = class(TListObject)
|
---|
22 | RootDir: string;
|
---|
23 | function FindByName(Name: string): TRegistredPage;
|
---|
24 | procedure RegisterPage(PageClass: TWebPageClass; out Reference; Path: string);
|
---|
25 | function ProducePage(HandlerData: THTTPHandlerData): Boolean;
|
---|
26 | end;
|
---|
27 |
|
---|
28 | { TWebApp }
|
---|
29 |
|
---|
30 | TWebApp = class(TComponent)
|
---|
31 | private
|
---|
32 | FOnPageProduce: TOnProduceEvent;
|
---|
33 | FOnInitialize: TNotifyEvent;
|
---|
34 | FServerType: THTTPServerType;
|
---|
35 | function DumpExceptionCallStack(E: Exception): string;
|
---|
36 | procedure HTTPServerRequest(HandlerData: THTTPHandlerData);
|
---|
37 | procedure SetServerType(AValue: THTTPServerType);
|
---|
38 | public
|
---|
39 | HTTPServer: THTTPServer;
|
---|
40 | HTTPSessionStorageFile: THTTPSessionStorageFile;
|
---|
41 | LogException: Boolean;
|
---|
42 | procedure ShowException(E: Exception);
|
---|
43 | constructor Create(AOwner: TComponent); override;
|
---|
44 | destructor Destroy; override;
|
---|
45 | procedure Run;
|
---|
46 | published
|
---|
47 | property OnPageProduce: TOnProduceEvent read FOnPageProduce write FOnPageProduce;
|
---|
48 | property OnInitialize: TNotifyEvent read FOnInitialize write FOnInitialize;
|
---|
49 | property ServerType: THTTPServerType read FServerType write SetServerType;
|
---|
50 | end;
|
---|
51 |
|
---|
52 |
|
---|
53 | procedure Register;
|
---|
54 |
|
---|
55 | implementation
|
---|
56 |
|
---|
57 | uses
|
---|
58 | UHTTPServerCGI, UHTTPServerTCP, UHTTPServerTurboPower;
|
---|
59 |
|
---|
60 |
|
---|
61 | procedure Register;
|
---|
62 | begin
|
---|
63 | RegisterComponents('CoolWeb', [TWebApp]);
|
---|
64 | end;
|
---|
65 |
|
---|
66 |
|
---|
67 | { TPageList }
|
---|
68 |
|
---|
69 | function TPageList.FindByName(Name: string): TRegistredPage;
|
---|
70 | var
|
---|
71 | I: Integer;
|
---|
72 | begin
|
---|
73 | I := 0;
|
---|
74 | while (I < Count) and (TRegistredPage(Items[I]).Name <> Name) do Inc(I);
|
---|
75 | if I < Count then Result := TRegistredPage(Items[I])
|
---|
76 | else Result := nil;
|
---|
77 | end;
|
---|
78 |
|
---|
79 | { TWebApp }
|
---|
80 |
|
---|
81 | procedure TWebApp.Run;
|
---|
82 | begin
|
---|
83 | if Assigned(FOnInitialize) then FOnInitialize(Self);
|
---|
84 | HTTPServer.Run;
|
---|
85 | if (ServerType = stCGI) or (ServerType = stTCP) then
|
---|
86 | Application.Terminate;
|
---|
87 | end;
|
---|
88 |
|
---|
89 | function TWebApp.DumpExceptionCallStack(E: Exception): string;
|
---|
90 | var
|
---|
91 | I: Integer;
|
---|
92 | Frames: PPointer;
|
---|
93 | Report: string;
|
---|
94 | begin
|
---|
95 | Report := 'Program exception! ' + LineEnding +
|
---|
96 | 'Stacktrace:' + LineEnding + LineEnding;
|
---|
97 | if E <> nil then begin
|
---|
98 | Report := Report + 'Exception class: ' + E.ClassName + LineEnding +
|
---|
99 | 'Message: ' + E.Message + LineEnding;
|
---|
100 | end;
|
---|
101 | Report := Report + BackTraceStrFunc(ExceptAddr);
|
---|
102 | Frames := ExceptFrames;
|
---|
103 | for I := 0 to ExceptFrameCount - 1 do
|
---|
104 | Report := Report + LineEnding + BackTraceStrFunc(PointerArray(Frames)[I]);
|
---|
105 | Result := Report;
|
---|
106 | end;
|
---|
107 |
|
---|
108 | procedure TPageList.RegisterPage(PageClass: TWebPageClass; out Reference;
|
---|
109 | Path: string);
|
---|
110 | var
|
---|
111 | NewPage: TRegistredPage;
|
---|
112 | Instance: TWebPage;
|
---|
113 | begin
|
---|
114 | NewPage := TRegistredPage(AddNew(TRegistredPage.Create));
|
---|
115 | // NewPage.Page := PageClass.Create(Self);
|
---|
116 | NewPage.Page := PageClass.Create(nil);
|
---|
117 | NewPage.Name := Path;
|
---|
118 | TWebPage(Reference) := NewPage.Page;
|
---|
119 | end;
|
---|
120 |
|
---|
121 | function TPageList.ProducePage(HandlerData: THTTPHandlerData): Boolean;
|
---|
122 | var
|
---|
123 | Page: TRegistredPage;
|
---|
124 | PageName: string;
|
---|
125 | begin
|
---|
126 | with HandlerData do begin
|
---|
127 | if Request.Path.Count > 0 then PageName := Request.Path[0]
|
---|
128 | else PageName := '';
|
---|
129 | Page := FindByName(PageName);
|
---|
130 | if Assigned(Page) then begin
|
---|
131 | Page.Page.OnProduce(HandlerData);
|
---|
132 | Result := True;
|
---|
133 | end else Result := False;
|
---|
134 | end;
|
---|
135 | end;
|
---|
136 |
|
---|
137 | procedure TWebApp.HTTPServerRequest(HandlerData: THTTPHandlerData);
|
---|
138 | begin
|
---|
139 | if Assigned(FOnPageProduce) then
|
---|
140 | FOnPageProduce(HandlerData);
|
---|
141 | end;
|
---|
142 |
|
---|
143 | procedure TWebApp.SetServerType(AValue: THTTPServerType);
|
---|
144 | begin
|
---|
145 | if FServerType = AValue then Exit;
|
---|
146 | FServerType := AValue;
|
---|
147 | HTTPServer.Free;
|
---|
148 | case FServerType of
|
---|
149 | stCGI: HTTPServer := THTTPServerCGI.Create(nil);
|
---|
150 | stTCP: HTTPServer := THTTPServerTCP.Create(nil);
|
---|
151 | stTurboPower: HTTPServer := THTTPServerTurboPower.Create(nil);
|
---|
152 | end;
|
---|
153 | HTTPServer.OnRequest := HTTPServerRequest;
|
---|
154 | end;
|
---|
155 |
|
---|
156 | procedure TWebApp.ShowException(E: Exception);
|
---|
157 | var
|
---|
158 | hstdout: ^Text;
|
---|
159 | begin
|
---|
160 | if not LogException then begin
|
---|
161 | hstdout := @stdout;
|
---|
162 | WriteLn(hstdout^, 'Content-type: text/html');
|
---|
163 | WriteLn(hstdout^);
|
---|
164 | Writeln(hstdout^, 'An unhandled exception occurred: ' + E.Message + '<br>');
|
---|
165 | WriteLn(hstdout^, StringReplace(DumpExceptionCallStack(E), LineEnding, '<br>', [rfReplaceAll]));
|
---|
166 | end else begin
|
---|
167 | hstdout := @stdout;
|
---|
168 | WriteLn(hstdout^, 'Content-type: text/html');
|
---|
169 | WriteLn(hstdout^);
|
---|
170 | WriteLn(hstdout^, 'Error occured during page generation.');
|
---|
171 | hstdout := @stderr;
|
---|
172 | Writeln(hstdout^, 'An unhandled exception occurred: ' + E.Message + '<br>');
|
---|
173 | WriteLn(hstdout^, DumpExceptionCallStack(E));
|
---|
174 | end;
|
---|
175 | end;
|
---|
176 |
|
---|
177 | constructor TWebApp.Create(AOwner: TComponent);
|
---|
178 | begin
|
---|
179 | inherited Create(AOwner);
|
---|
180 | HTTPServer := THTTPServerCGI.Create(nil);
|
---|
181 | HTTPServer.OnRequest := HTTPServerRequest;
|
---|
182 | end;
|
---|
183 |
|
---|
184 | destructor TWebApp.Destroy;
|
---|
185 | begin
|
---|
186 | HTTPServer.Free;
|
---|
187 | inherited Destroy;
|
---|
188 | end;
|
---|
189 |
|
---|
190 |
|
---|
191 | initialization
|
---|
192 |
|
---|
193 | finalization
|
---|
194 |
|
---|
195 | end.
|
---|
196 |
|
---|