Delphi TIdTcpServer 获取POST 浏览器发送的参数
Delphi TIdTcpServer get POST parameters sent by browser
我正在开发一个简单的 Web 服务器来与我在浏览器中运行的 Web 应用程序进行通信。
我成功地创建了一个IdTcpServer 并获得了浏览器提交的RequestHeaders。
我不知道如何获取表单的 POST 参数。
到目前为止,这是我的代码:
procedure TMyServer.WebServerExecute(AContext: TIdContext);
var
RawData: String;
TRequestHeader: TStringList;
begin
TRequestHeader := TStringList.Create;
// GET Request Headers
RawData := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
while RawData <> '' do
begin
TRequestHeader.Add(RawData);
RawData := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
end;
// How To get POST or GET Parameters of the HTML form?
// ...
// Respond to the Client
Respond(...);
TRequestHeader.Free;
end;
收到请求 headers 后,您需要分析它们以了解消息 body 是否存在,以及它以何种格式编码以便您可以正确阅读(请参阅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
参数。请求 headers 将在 ARequestInfo.RawHeaders
属性 和各种 sub-properties(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;
我正在开发一个简单的 Web 服务器来与我在浏览器中运行的 Web 应用程序进行通信。
我成功地创建了一个IdTcpServer 并获得了浏览器提交的RequestHeaders。 我不知道如何获取表单的 POST 参数。
到目前为止,这是我的代码:
procedure TMyServer.WebServerExecute(AContext: TIdContext);
var
RawData: String;
TRequestHeader: TStringList;
begin
TRequestHeader := TStringList.Create;
// GET Request Headers
RawData := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
while RawData <> '' do
begin
TRequestHeader.Add(RawData);
RawData := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
end;
// How To get POST or GET Parameters of the HTML form?
// ...
// Respond to the Client
Respond(...);
TRequestHeader.Free;
end;
收到请求 headers 后,您需要分析它们以了解消息 body 是否存在,以及它以何种格式编码以便您可以正确阅读(请参阅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
参数。请求 headers 将在 ARequestInfo.RawHeaders
属性 和各种 sub-properties(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;