#1 2012-09-03 16:54:27

profh
Member
Registered: 2010-07-02
Posts: 159

response part of file while OutContentType equals HTTP_RESP_STATICFILE

while using THttpApiServer, how to response part of file according to 'Range: bytes=***-***' in InHeaders?

thanks.

Offline

#2 2012-09-04 12:30:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

OutContentType equals HTTP_RESP_STATICFILE +  'Range: bytes=***-***' in InHeaders is not handled in the current code.

Here is what I found in http://msdn.microsoft.com/en-us/library … s.85).aspx

You may try to add the HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES flag in THttpApiServer.Execute:

Http.SendHttpResponse(fReqQueue,Req^.RequestId,HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES,Resp^,nil,bytesSent);

But I'm not sure it will work as expected.

Please provide some feedback about it.

Offline

#3 2012-09-05 13:26:28

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

Here is what  i m learning about: http://xxm.sourceforge.net/

Perhaps "hsys" of it is what i m looking for...

Offline

#4 2012-09-05 14:33:09

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

i got it...

here is the code i just modify:

          if OutContentType=HTTP_RESP_STATICFILE then begin
            // response is file -> let http.sys serve it (OutContent is UTF-8)
            FileHandle := FileOpen(
              {$ifdef UNICODE}UTF8ToUnicodeString{$else}Utf8ToAnsi{$endif}(OutContent),
              fmOpenRead or fmShareDenyNone);
            if PtrInt(FileHandle)<0 then
              SendError(404,SysErrorMessage(GetLastError)) else
            try
              DataChunk.DataChunkType := hctFromFileHandle;
              DataChunk.FromFileHandle.FileHandle := FileHandle;
              rangstart := 0;
              ranglength := -1;
              getrangstartend;
              DataChunk.FromFileHandle.ByteRange.StartingOffset.QuadPart := rangstart;
              Int64(DataChunk.FromFileHandle.ByteRange.Length.QuadPart) := ranglength; // to eof
              Resp^.EntityChunkCount := 1;
              Resp^.pEntityChunks := @DataChunk;
              Http.SendHttpResponse(fReqQueue,Req^.RequestId,1,Resp^,nil,bytesSent);
            finally
              FileClose(FileHandle);
            end;
          end else begin

getrangstartend is used to get rangstart and ranglength from inHeaders.
the flags of Http.SendHttpResponse is changed to 1 from 0.


and it works now.

thanks,ab.

Offline

#5 2012-09-05 16:08:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

How do you implement "getrangstartend" method - I guess from Req^.Headers[reqRange]?

Is not HttpHeaderIfRange header necessary?

Offline

#6 2012-09-05 16:31:04

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

procedure THttpApiServer.Execute;
var Req: PHTTP_REQUEST;
    ReqID: HTTP_REQUEST_ID;
    ReqBuf, RespBuf: TSockData;
    i: integer;
    flags, bytesRead, bytesSent: cardinal;
    Err: HRESULT;
    InCompressAccept: THttpSocketCompressSet;
    InContentLength, InContentLengthRead: cardinal;
    InContentLengthStr: TSockData;
    InContentEncoding, InAcceptEncoding: TSockData;
    OutContentEncoding: TSockData;
    InURL, InMethod, InHeaders, InContent, InContentType: TSockData;
    OutContent, OutContentType, OutCustomHeader, OutStatus: TSockData;
    OutContentTypeP: PAnsiChar absolute OutContentType;
    FileHandle: THandle;
    Resp: PHTTP_RESPONSE;
    BufRead: PAnsiChar;
    Heads: array of HTTP_UNKNOWN_HEADER;
    DataChunk: HTTP_DATA_CHUNK;

    rangstart,ranglength:int64;
  procedure getrangstartend;
  var
    i,ipos:integer;
    ssl:TStringlist;
    tmpstr:string;
  begin
    rangstart := 0;
    ranglength := -1;
    if (trim(inHeaders) = '') then exit;

    ssl := TStringlist.Create;
    ssl.Text := inHeaders;
    for i := 0 to ssl.Count -1 do
    begin
      tmpstr := trim(ssl.Strings[i]);
      if (pos('range:',lowercase(tmpstr)) = 1) then
      begin
        tmpstr := trim(copy(tmpstr,7,length(tmpstr) - 6));
        if (pos('bytes=',lowercase(tmpstr)) = 1) then
        begin
          tmpstr := trim(copy(tmpstr,7,length(tmpstr) - 6));
          ipos := pos('-',tmpstr);
          if (ipos > 0) then
          begin
            try
              rangstart := strtoint64(trim(copy(tmpstr,1,ipos - 1)));
            except
              rangstart := 0;
            end;
            try
              ranglength := strtoint64(trim(copy(tmpstr,ipos + 1,
                                           length(tmpstr) - ipos + 1)));
            except
              ranglength := -1;
            end;
            if (ranglength > rangstart) then
              ranglength := ranglength - rangstart
            else
              ranglength := -1;
          end
          else
          begin
            ranglength := -1;

            try
              rangstart := strtoint64(trim(tmpstr));
            except
              rangstart := 0;
            end;
          end;
        end;
      end;
    end;
    ssl.free;
  end;

  procedure SendError(StatusCode: cardinal; const ErrorMsg: string);
  begin
    Resp^.SetStatus(StatusCode,OutStatus,@DataChunk,TSockData(ErrorMsg));
    Http.SendHttpResponse(fReqQueue,Req^.RequestId,0,Resp^,nil,bytesSent);
  end;

begin

getrangstartend is not so good smile

Last edited by profh (2012-09-05 16:42:56)

Offline

#7 2012-09-05 17:16:34

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

Could you try this alternative implementation:
http://synopse.info/fossil/fdiff?v1=e10 … 6b85e7f7d8

Sounds more "mORMot-ish". wink

Thanks for the feedback.

Offline

#8 2012-09-05 17:22:10

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

Offline

#9 2012-09-07 03:09:43

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

thanks, and it s great.

another problem i can not understand is:

i download a file from server using many segments, the range of the last segment perhaps is 12345,678.
if i download the last segment with range of 12345,678, it returns fales, but if i use 12345,-1, it is ok.

BTW,it s terrific about http://blog.synopse.info/post/2012/09/0 … laboration

Offline

#10 2012-09-07 05:57:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

Do you mean 12345-67890 ?

12345,678 does not mean anything IMHO.

Offline

#11 2012-09-07 09:18:12

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

sorry,678 means the rang length,so i mean 12345,12345 + 678.

Offline

#12 2012-09-07 09:45:53

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

As far as I understood the standard, you can not use ',' nor '+' in the range.

Examples of byte-content-range-spec values, assuming that the entity contains a total of 1234 bytes:

      . The first 500 bytes:
       bytes 0-499/1234
      . The second 500 bytes:
       bytes 500-999/1234
      . All except for the first 500 bytes:
       bytes 500-1233/1234
      . The last 500 bytes:
       bytes 734-1233/1234

See http://www.w3.org/Protocols/rfc2616/rfc … sec14.35.1

Offline

#13 2012-09-07 09:53:56

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

yes, what i mean is that it returns false when i get the last 500 bytes,

the syntax is right just like above standard,because the previous segments are all correct.

Offline

#14 2012-09-07 09:59:08

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,204
Website

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

Is it not because the last chunk range exceed the file length?

We compute RangeLength := GetNextItemUInt64(R)-RangeStart+1 as it should be (499-0+1=500 bytes for '0-499/1234').

Perhaps your request is too big: last index should be < total length, and be the index of the last character.

Offline

#15 2012-09-07 15:56:40

profh
Member
Registered: 2010-07-02
Posts: 159

Re: response part of file while OutContentType equals HTTP_RESP_STATICFILE

u are right, and i got it.

many thanks.

Offline

Board footer

Powered by FluxBB