| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- { $HDR$}
- {**********************************************************************}
- { Unit archived using Team Coherence }
- { Team Coherence is Copyright 2002 by Quality Software Components }
- { }
- { For further information / comments, visit our WEB site at }
- { http://www.TeamCoherence.com }
- {**********************************************************************}
- {}
- { $Log: 10197: IdHTTPWebBrokerBridge.pas
- {
- { Rev 1.1 05.6.2003 ã. 11:27:16 DBondzhev
- { Header vars are not the same like for ISAPI in webBroker
- }
- {
- { Rev 1.0 2002.11.12 10:41:30 PM czhower
- }
- unit IdHTTPWebBrokerBridge;
- {$I IdCompilerDefines.inc}
- (*
- Original Author: Dave Nottage.
- Modified by: Grahame Grieve
- Modified by: Chad Z. Hower (Kudzu)
- *)
- interface
- uses
- Classes,
- HTTPApp,
- IdCustomHTTPServer, IdTCPServer, IdIOHandlerSocket,
- WebBroker;
- type
- TIdHTTPAppRequest = class(TWebRequest)
- protected
- FRequestInfo : TIdHTTPRequestInfo;
- FResponseInfo : TIdHTTPResponseInfo;
- FThread : TIdPeerThread;
- FClientCursor : Integer;
- //
- function GetDateVariable(Index: Integer): TDateTime; override;
- function GetIntegerVariable(Index: Integer): Integer; override;
- function GetStringVariable(Index: Integer): string; override;
- public
- constructor Create(AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo;
- AResponseInfo: TIdHTTPResponseInfo);
- function GetFieldByName(const Name: string): string; override;
- function ReadClient(var Buffer; Count: Integer): Integer; override;
- function ReadString(Count: Integer): string; override;
- function TranslateURI(const URI: string): string; override;
- function WriteClient(var ABuffer; ACount: Integer): Integer; override;
- {$IFDEF VCL6ORABOVE}
- function WriteHeaders(StatusCode: Integer; const ReasonString, Headers: string): Boolean; override;
- {$ENDIF}
- function WriteString(const AString: string): Boolean; override;
- end;
- TIdHTTPAppResponse = class(TWebResponse)
- protected
- FContent: string;
- FRequestInfo: TIdHTTPRequestInfo;
- FResponseInfo: TIdHTTPResponseInfo;
- FSent: Boolean;
- FThread: TIdPeerThread;
- //
- function GetContent: string; override;
- function GetDateVariable(Index: Integer): TDateTime; override;
- function GetStatusCode: Integer; override;
- function GetIntegerVariable(Index: Integer): Integer; override;
- function GetLogMessage: string; override;
- function GetStringVariable(Index: Integer): string; override;
- procedure SetContent(const AValue: string); override;
- procedure SetContentStream(AValue: TStream); override;
- procedure SetStatusCode(AValue: Integer); override;
- procedure SetStringVariable(Index: Integer; const Value: string); override;
- procedure SetDateVariable(Index: Integer; const Value: TDateTime); override;
- procedure SetIntegerVariable(Index: Integer; Value: Integer); override;
- procedure SetLogMessage(const Value: string); override;
- procedure MoveCookiesAndCustomHeaders;
- public
- constructor Create(AHTTPRequest: TWebRequest; AThread: TIdPeerThread;
- ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
- procedure SendRedirect(const URI: string); override;
- procedure SendResponse; override;
- procedure SendStream(AStream: TStream); override;
- function Sent: Boolean; override;
- end;
- TIdHTTPWebBrokerBridge = class(TIdCustomHTTPServer)
- protected
- FWebModuleClass: TComponentClass;
- //
- procedure DoCommandGet(AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo;
- AResponseInfo: TIdHTTPResponseInfo); override;
- public
- constructor Create(AOwner: TComponent); override;
- procedure RegisterWebModuleClass(AClass: TComponentClass);
- end;
- implementation
- uses
- IdException, IdHTTPHeaderInfo, IdGlobal, IdCookie,
- SysUtils, Math;
- type
- // Make HandleRequest accessible
- TWebDispatcherAccess = class(TCustomWebDispatcher);
- const
- INDEX_RESP_Version = 0;
- INDEX_RESP_ReasonString = 1;
- INDEX_RESP_Server = 2;
- INDEX_RESP_WWWAuthenticate = 3;
- INDEX_RESP_Realm = 4;
- INDEX_RESP_Allow = 5;
- INDEX_RESP_Location = 6;
- INDEX_RESP_ContentEncoding = 7;
- INDEX_RESP_ContentType = 8;
- INDEX_RESP_ContentVersion = 9;
- INDEX_RESP_DerivedFrom = 10;
- INDEX_RESP_Title = 11;
- //
- INDEX_RESP_ContentLength = 0;
- //
- INDEX_RESP_Date = 0;
- INDEX_RESP_Expires = 1;
- INDEX_RESP_LastModified = 2;
- //
- //Borland coder didn't define constants in HTTPApp
- INDEX_Method = 0;
- INDEX_ProtocolVersion = 1;
- INDEX_URL = 2;
- INDEX_Query = 3;
- INDEX_PathInfo = 4;
- INDEX_PathTranslated = 5;
- INDEX_CacheControl = 6;
- INDEX_Date = 7;
- INDEX_Accept = 8;
- INDEX_From = 9;
- INDEX_Host = 10;
- INDEX_IfModifiedSince = 11;
- INDEX_Referer = 12;
- INDEX_UserAgent = 13;
- INDEX_ContentEncoding = 14;
- INDEX_ContentType = 15;
- INDEX_ContentLength = 16;
- INDEX_ContentVersion = 17;
- INDEX_DerivedFrom = 18;
- INDEX_Expires = 19;
- INDEX_Title = 20;
- INDEX_RemoteAddr = 21;
- INDEX_RemoteHost = 22;
- INDEX_ScriptName = 23;
- INDEX_ServerPort = 24;
- INDEX_Content = 25;
- INDEX_Connection = 26;
- INDEX_Cookie = 27;
- INDEX_Authorization = 28;
- { TIdHTTPAppRequest }
- constructor TIdHTTPAppRequest.Create(AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
- Var
- i: Integer;
- begin
- FThread := AThread;
- FRequestInfo := ARequestInfo;
- FResponseInfo := AResponseInfo;
- inherited Create;
- FClientCursor := 0;
- for i := 0 to ARequestInfo.Cookies.Count - 1 do begin
- CookieFields.Add(ARequestInfo.Cookies[i].ClientCookie);
- end;
- end;
- function TIdHTTPAppRequest.GetDateVariable(Index: Integer): TDateTime;
- var
- LValue: string;
- begin
- LValue := GetStringVariable(Index);
- if Length(LValue) > 0 then begin
- Result := ParseDate(LValue)
- end else begin
- Result := -1;
- end;
- end;
- function TIdHTTPAppRequest.GetIntegerVariable(Index: Integer): Integer;
- begin
- Result := StrToIntDef(GetStringVariable(Index), -1)
- end;
- function TIdHTTPAppRequest.GetStringVariable(Index: Integer): string;
- var
- s: string;
- begin
- case Index of
- INDEX_Method : Result := FRequestInfo.Command;
- INDEX_ProtocolVersion : Result := FRequestInfo.Version;
- INDEX_URL : Result := FRequestInfo.Document;
- INDEX_Query : Result := FRequestInfo.UnparsedParams;
- INDEX_PathInfo : Result := FRequestInfo.Document;
- INDEX_PathTranslated : Result := FRequestInfo.Document; // it's not clear quite what should be done here - we can't translate to a path
- INDEX_CacheControl : Result := GetFieldByName('CACHE_CONTROL'); {do not localize}
- INDEX_Date : Result := GetFieldByName('DATE'); {do not localize}
- INDEX_Accept : Result := FRequestInfo.Accept;
- INDEX_From : Result := FRequestInfo.From;
- INDEX_Host: begin
- s := FRequestInfo.Host;
- Result := Fetch(s, ':');
- end;
- INDEX_IfModifiedSince : Result := GetFieldByName('If-Modified-Since'); {do not localize}
- INDEX_Referer : Result := FRequestInfo.Referer;
- INDEX_UserAgent : Result := FRequestInfo.UserAgent;
- INDEX_ContentEncoding : Result := FRequestInfo.ContentEncoding;
- INDEX_ContentType : Result := FRequestInfo.ContentType;
- INDEX_ContentLength : Result := IntToStr(Length(FRequestInfo.UnparsedParams));
- INDEX_ContentVersion : Result := GetFieldByName('CONTENT_VERSION'); {do not localize}
- INDEX_DerivedFrom : Result := GetFieldByName('DERIVED_FROM'); {do not localize}
- INDEX_Expires : Result := GetFieldByName('Expires'); {do not localize}
- INDEX_Title : Result := GetFieldByName('TITLE'); {do not localize}
- INDEX_RemoteAddr : Result := FRequestInfo.RemoteIP;
- INDEX_RemoteHost : Result := GetFieldByName('REMOTE_HOST'); {do not localize}
- INDEX_ScriptName : Result := '';
- INDEX_ServerPort: begin
- Result := FRequestInfo.Host;
- Fetch(Result, ':');
- if Length(Result) = 0 then begin
- Result := IntToStr(TIdIOHandlerSocket(FThread.Connection.IOHandler).Binding.Port);
- // Result := '80';
- end;
- end;
- INDEX_Content : Result := FRequestInfo.UnparsedParams;
- INDEX_Connection : Result := GetFieldByName('CONNECTION'); {do not localize}
- INDEX_Cookie : Result := ''; // not available at present. FRequestInfo.Cookies....;
- INDEX_Authorization : Result := GetFieldByName('AUTHORIZATION'); {do not localize}
- else
- Result := '';
- end;
- end;
- function TIdHTTPAppRequest.GetFieldByName(const Name: string): string;
- begin
- Result := FRequestInfo.RawHeaders.Values[Name];
- end;
- function TIdHTTPAppRequest.ReadClient(var Buffer; Count: Integer): Integer;
- begin
- Result := Min(Count, length(FRequestInfo.UnparsedParams)) - FClientCursor;
- if Result > 0 then begin
- Move(FRequestInfo.UnparsedParams[FClientCursor + 1], Buffer, Result);
- Inc(FClientCursor, Result);
- end else begin
- // well, it shouldn't be less than 0. but let's not take chances
- Result := 0;
- end;
- end;
- function TIdHTTPAppRequest.ReadString(Count: Integer): string;
- var
- LLength: Integer;
- begin
- LLength := Min(Count, length(FRequestInfo.UnparsedParams)) - FClientCursor;
- if LLength > 0 then
- begin
- Result := copy(FRequestInfo.UnparsedParams, FClientCursor, LLength);
- inc(FClientCursor, LLength);
- end
- else
- Result := '';
- end;
- function TIdHTTPAppRequest.TranslateURI(const URI: string): string;
- begin
- // we don't have the concept of a path translation. It's not quite clear
- // what to do about this. Comments welcome ([email protected])
- Result := URI;
- end;
- {$IFDEF VCL6ORABOVE}
- function TIdHTTPAppRequest.WriteHeaders(StatusCode: Integer; const ReasonString, Headers: string): Boolean;
- begin
- FResponseInfo.ResponseNo := StatusCode;
- FResponseInfo.ResponseText := ReasonString;
- FResponseInfo.CustomHeaders.Add(Headers);
- FResponseInfo.WriteHeader;
- Result := True;
- end;
- {$ENDIF}
- function TIdHTTPAppRequest.WriteString(const AString: string): Boolean;
- begin
- WriteClient(PChar(AString)^, Length(AString));
- Result := True;
- end;
- function TIdHTTPAppRequest.WriteClient(var ABuffer; ACount: Integer): Integer;
- begin
- FThread.Connection.WriteBuffer(ABuffer, ACount);
- Result := ACount;
- end;
- { TIdHTTPAppResponse }
- constructor TIdHTTPAppResponse.Create(AHTTPRequest: TWebRequest; AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
- begin
- FThread := AThread;
- FRequestInfo := ARequestInfo;
- FResponseInfo := AResponseInfo;
- inherited Create(AHTTPRequest);
- if Length(FHTTPRequest.ProtocolVersion) = 0 then begin
- Version := '1.0';
- end;
- StatusCode := 200;
- LastModified := -1;
- Expires := -1;
- Date := -1;
- ContentType := 'text/html';
- end;
- function TIdHTTPAppResponse.GetContent: string;
- begin
- Result := FResponseInfo.ContentText;
- end;
- function TIdHTTPAppResponse.GetLogMessage: string;
- begin
- Result := '';
- end;
- function TIdHTTPAppResponse.GetStatusCode: Integer;
- begin
- Result := FResponseInfo.ResponseNo;
- end;
- function TIdHTTPAppResponse.GetDateVariable(Index: Integer): TDateTime;
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_Date : Result := FResponseInfo.Date;
- INDEX_RESP_Expires : Result := FResponseInfo.Expires;
- INDEX_RESP_LastModified : Result := FResponseInfo.LastModified;
- else
- raise EIdException.Create('Invalid Index '+inttostr(Index)+' in TIdHTTPAppResponse.GetDateVariable');
- end;
- end;
- procedure TIdHTTPAppResponse.SetDateVariable(Index: Integer; const Value: TDateTime);
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_Date : FResponseInfo.Date := Value;
- INDEX_RESP_Expires : FResponseInfo.Expires := Value;
- INDEX_RESP_LastModified : FResponseInfo.LastModified := Value;
- else
- raise EIdException.Create('Invalid Index '+inttostr(Index)+' in TIdHTTPAppResponse.SetDateVariable');
- end;
- end;
- function TIdHTTPAppResponse.GetIntegerVariable(Index: Integer): Integer;
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_ContentLength: Result := FResponseInfo.ContentLength;
- else
- raise EIdException.Create('Invalid Index '+inttostr(Index)+' in TIdHTTPAppResponse.GetIntegerVariable');
- end;
- end;
- procedure TIdHTTPAppResponse.SetIntegerVariable(Index, Value: Integer);
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_ContentLength: FResponseInfo.ContentLength := Value;
- else
- raise EIdException.Create('Invalid Index '+inttostr(Index)+' in TIdHTTPAppResponse.SetIntegerVariable');
- end;
- end;
- function TIdHTTPAppResponse.GetStringVariable(Index: Integer): string;
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_Version :Result := FRequestInfo.Version;
- INDEX_RESP_ReasonString :Result := FResponseInfo.ResponseText;
- INDEX_RESP_Server :Result := FResponseInfo.Server;
- INDEX_RESP_WWWAuthenticate :Result := FResponseInfo.WWWAuthenticate.Text;
- INDEX_RESP_Realm :Result := FResponseInfo.AuthRealm;
- INDEX_RESP_Allow :Result := FResponseInfo.CustomHeaders.Values['Allow'];
- INDEX_RESP_Location :Result := FResponseInfo.Location;
- INDEX_RESP_ContentEncoding :Result := FResponseInfo.ContentEncoding;
- INDEX_RESP_ContentType :Result := FResponseInfo.ContentType;
- INDEX_RESP_ContentVersion :Result := FResponseInfo.ContentVersion;
- INDEX_RESP_DerivedFrom :Result := FResponseInfo.CustomHeaders.Values['Derived-From'];
- INDEX_RESP_Title :Result := FResponseInfo.CustomHeaders.Values['Title'];
- else
- raise EIdException.Create('Invalid Index ' + IntToStr(Index)
- + ' in TIdHTTPAppResponse.GetStringVariable');
- end;
- end;
- procedure TIdHTTPAppResponse.SetStringVariable(Index: Integer; const Value: string);
- begin
- //TODO: resource string these
- case Index of
- INDEX_RESP_Version :EIdException.Create('TIdHTTPAppResponse.SetStringVariable: Cannot set the version');
- INDEX_RESP_ReasonString :FResponseInfo.ResponseText := Value;
- INDEX_RESP_Server :FResponseInfo.Server := Value;
- INDEX_RESP_WWWAuthenticate :FResponseInfo.WWWAuthenticate.Text := Value;
- INDEX_RESP_Realm :FResponseInfo.AuthRealm := Value;
- INDEX_RESP_Allow :FResponseInfo.CustomHeaders.Values['Allow'] := Value;
- INDEX_RESP_Location :FResponseInfo.Location := Value;
- INDEX_RESP_ContentEncoding :FResponseInfo.ContentEncoding := Value;
- INDEX_RESP_ContentType :FResponseInfo.ContentType := Value;
- INDEX_RESP_ContentVersion :FResponseInfo.ContentVersion := Value;
- INDEX_RESP_DerivedFrom :FResponseInfo.CustomHeaders.Values['Derived-From'] := Value;
- INDEX_RESP_Title :FResponseInfo.CustomHeaders.Values['Title'] := Value;
- else
- raise EIdException.Create('Invalid Index ' + IntToStr(Index)
- + ' in TIdHTTPAppResponse.SetStringVariable');
- end;
- end;
- procedure TIdHTTPAppResponse.SendRedirect(const URI: string);
- begin
- FSent := True;
- MoveCookiesAndCustomHeaders;
- FResponseInfo.Redirect(URI);
- end;
- procedure TIdHTTPAppResponse.SendResponse;
- begin
- FSent := True;
- // Reset to -1 so Indy will auto set it
- FResponseInfo.ContentLength := -1;
- MoveCookiesAndCustomHeaders;
- FResponseInfo.WriteContent;
- end;
- procedure TIdHTTPAppResponse.SendStream(AStream: TStream);
- begin
- FThread.Connection.WriteStream(AStream);
- end;
- function TIdHTTPAppResponse.Sent: Boolean;
- begin
- Result := FSent;
- end;
- procedure TIdHTTPAppResponse.SetContent(const AValue: string);
- begin
- FResponseInfo.ContentText := AValue;
- FResponseInfo.ContentLength := Length(AValue);
- end;
- procedure TIdHTTPAppResponse.SetLogMessage(const Value: string);
- begin
- // logging not supported
- end;
- procedure TIdHTTPAppResponse.SetStatusCode(AValue: Integer);
- begin
- FResponseInfo.ResponseNo := AValue;
- end;
- procedure TIdHTTPAppResponse.SetContentStream(AValue: TStream);
- begin
- inherited;
- FResponseInfo.ContentStream := AValue;
- end;
- procedure TIdHTTPAppResponse.MoveCookiesAndCustomHeaders;
- Var
- i: Integer;
- begin
- for i := 0 to Cookies.Count - 1 do begin
- with FResponseInfo.Cookies.Add do begin
- CookieText := Cookies[i].HeaderValue
- end;
- end;
- FResponseInfo.CustomHeaders.Clear;
- for i := 0 to CustomHeaders.Count - 1 do begin
- FResponseInfo.CustomHeaders.Values[CustomHeaders.Names[i]] :=
- CustomHeaders.Values[CustomHeaders.Names[i]];
- end;
- end;
- { TIdHTTPWebBrokerBridge }
- constructor TIdHTTPWebBrokerBridge.Create;
- begin
- inherited;
- FOkToProcessCommand := True;
- end;
- procedure TIdHTTPWebBrokerBridge.DoCommandGet(AThread: TIdPeerThread;
- ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
- var
- LRequest: TIdHTTPAppRequest;
- LResponse: TIdHTTPAppResponse;
- LWebModule: TCustomWebDispatcher;
- begin
- LRequest := TIdHTTPAppRequest.Create(AThread, ARequestInfo, AResponseInfo); try
- LResponse := TIdHTTPAppResponse.Create(LRequest, AThread, ARequestInfo, AResponseInfo); try
- // WebBroker will free it and we cannot change this behaviour
- AResponseInfo.FreeContentStream := False;
- // There are better ways in D6, but this works in D5
- LWebModule := FWebModuleClass.Create(nil) as TCustomWebDispatcher; try
- if TWebDispatcherAccess(LWebModule).DispatchAction(LRequest, LResponse) then begin
- if not LResponse.Sent then begin
- LResponse.SendResponse;
- end;
- end;
- finally FreeAndNil(LWebModule); end;
- finally FreeAndNil(LResponse); end;
- finally FreeAndNil(LRequest); end;
- end;
- procedure TIdHTTPWebBrokerBridge.RegisterWebModuleClass(AClass: TComponentClass);
- begin
- FWebModuleClass := AClass;
- end;
- end.
|