How to send a DELETE request with Indy 9?

1k Views Asked by At

I am trying to send HTTP DELETE request using Indy 9.

Attempt (like that):

type
  TIdHTTPAccess = class(TIdHTTP)
  end;

TIdHTTPAccess(IdHttp).DoRequest(hmDelete, deleteURL, nil, nil);

This doesn't work, because hmDelete skipped in TIdHTTPProtocol.BuildAndSendRequest.

Is there any chance, to send HTTP DELETE request using Indy 9?

Delpphi 7, Indy 9.00.10, part of unit IdHTTP;

procedure TIdHTTPProtocol.BuildAndSendRequest(AURI: TIdURI);
...
  case Request.Method of
    hmHead: FHTTP.WriteLn('HEAD ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    hmGet: FHTTP.WriteLn('GET ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    hmPost: FHTTP.WriteLn('POST ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    // HTTP 1.1 only
    hmOptions: FHTTP.WriteLn('OPTIONS ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    hmTrace: FHTTP.WriteLn('TRACE ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    hmPut: FHTTP.WriteLn('PUT ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
    hmConnect: FHTTP.WriteLn('CONNECT ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
  end;
...
1

There are 1 best solutions below

0
Remy Lebeau On BEST ANSWER

Calling TIdHTTP.DoRequest() directly is the correct way to send a DELETE request in Indy 9. Using an accessor class is one option to do that. Another option would be to derive a new component from TIdHTTP to add your own Delete() method that calls DoRequest() (much like TIdHTTP does in Indy 10):

type
  TMyHTTP = class(TIdHTTP)
  public
    procedure Delete(AURL: string; AResponseContent: TStream); overload;
    function Delete(AURL: string): string; overload;
  end;

procedure TMyHTTP.Delete(AURL: string; AResponseContent: TStream);
begin
  DoRequest(hmDelete, AURL, nil, AResponseContent);
end;

function TMyHTTP.Delete(AURL: string): string;
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    Delete(AURL, Stream);
    SetLength(Result, Stream.Size);
    Move(PChar(Stream.Memory)^, PChar(Result)^, Stream.Size);
  finally
    Stream.Free;
  end;
end;

However, that being said, you are using an outdated version of Indy 9. The last version is 9.0.50, and its BuildAndSendRequest() code is different than what you showed:

const
  ProtocolVersionString: array[TIdHTTPProtocolVersion] of string = ('1.0', '1.1'); {do not localize}
  MethodString: array[TIdHTTPMethod] of String = ('HEAD', 'GET', 'POST', 'OPTIONS', 'TRACE', 'PUT', 'DELETE', 'CONNECT'); {do not localize}

...

procedure TIdHTTPProtocol.BuildAndSendRequest(AURI: TIdURI);
var
  ...
begin
  ...
  FHTTP.WriteLn(MethodString[Request.Method] + ' ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
  ...
end;

The very issue you are having trouble with was addressed in the last revision made to Indy 9's IdHTTP.pas file (in SVN revision 35 on Dec 24 2007):

Updated TIdHTTPProtocol.BuildAndSendRequest() to use a string array of method names instead of using a 'case of' statement, which was originally missing an entry for 'hmDelete'.

You need to upgrade to an up-to-date version of Indy 9 (if not to Indy 10).

If that is not an option, then you will have to edit your current copy of IdHTTP.pas to add the missing hmDelete case, and then recompile Indy.