获得请求标头后,您需要对其进行分析以了解消息正文是否存在,以及以何种格式对其进行编码,以便您可以正确阅读它(请参阅RFC 2616 section 4.4),例如:
procedure TMyServer.WebServerConnect(AContext: TIdContext);
begin
AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
end;
procedure TMyServer.WebServerExecute(AContext: TIdContext);
var
ReqLine, Value: String;
I: Integer;
Size: Int64;
TRequestHeader: TIdHeaderList;
begin
TRequestHeader := TIdHeaderList.Create;
try
// GET Request Line ...
ReqLine := AContext.Connection.IOHandler.ReadLn;
// TODO: parse ReqLine as needed to extract HTTP version, resource, and query params ...
// GET Request Headers ...
repeat
Value := AContext.Connection.IOHandler.ReadLn;
if Value = '' then Break;
TRequestHeader.Add(Value);
until False;
// alternatively:
// AContext.Connection.IOHandler.Capture(TRequestHeader, '', False);
// get POST or GET data ...
Value := TRequestHeader.Values['Transfer-Encoding'];
if (Value <> '') and (not TextIsSame(Value, 'identity')) then
begin
repeat
Value := AContext.Connection.IOHandler.ReadLn;
I := Pos(';', Value);
if I > 0 then begin
Value := Copy(Value, 1, I - 1);
end;
Size := StrToInt64('$' + Trim(S));
if Size = 0 then begin
Break;
end;
// read specified number of bytes as needed ...
AContext.Connection.IOHandler.ReadLn; // read CRLF at end of chunk data
until False;
// read trailer headers
repeat
Value := AContext.Connection.IOHandler.ReadLn;
if (Value = '') then Break;
// update TRequestHeader as needed...
until False;
end
else
begin
Value := TRequestHeader.Values['Content-Length'];
if Value = '' then
begin
// respond with 411 error
Exit;
end;
Size := StrToInt64(Value);
// read specified number of bytes as needed ...
end;
// process request as needed, based on the value of
// ReqLine, TRequestHeader.Values['Content-Type'], etc ...
// Respond to the Client
Respond(...);
finally
TRequestHeader.Free;
end;
end;
话虽如此,Indy 有一个TIdHTTPServer 组件,它可以为您处理实现 HTTP 协议的艰巨工作(这并不是您认为的那么简单的任务)。你不应该为此使用TIdTCPServer。
您可以为TIdHTTPServer.OnCommandGet 事件分配一个处理程序,并根据需要使用提供的ARequestInfo 和AResponseInfo 参数。请求标头将位于ARequestInfo.RawHeaders 属性和各种子属性(ARequestInfo.ContentType、ARequestInfo.ContentLength 等)中。 GET/POST 数据将相应地位于 ARequestInfo.QueryParams、ARequestInfo.FormParams 和 ARequestInfo.PostStream 属性中,例如:
procedure TMyServer.WebServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
// use ARequestInfo.RawHeaders and ARequestInfo.QueryParams as needed ...
if ARequestInfo.CommandType = hcPOST then
begin
if IsHeaderMediaType(ARequestInfo.ContentType, 'application/x-www-form-urlencoded') then
begin
// use ARequestInfo.FormParams as needed ...
end
else begin
// use ARequestInfo.PostStream as needed ...
end;
end else
begin
// process GET/HEAD requests as needed ...
end;
// Respond to the Client, by populating AResponseInfo as needed ...
end;