anchor.diff:              exit(normal)
       end.
   
  +read_sub_chunks(Length, MaxChunkSize, Fun, FunState) when Length > MaxChunkSize ->
  +    Bin = recv(MaxChunkSize),
  +    NewState = Fun({size(Bin), Bin}, FunState),
  +    read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState);
  +
  +read_sub_chunks(Length, _MaxChunkSize, Fun, FunState) ->
  +    Fun({Length, read_chunk(Length)}, FunState).
  +    
   %% @spec serve_file(Path, DocRoot) -> Response
   %% @doc Serve a file relative to DocRoot.
   serve_file(Path, DocRoot) ->
  
positive.code:             Cached
      end.
  
  read_chunked_body(Max, Acc) ->
      case read_chunk_length() of
          0 ->
              read_chunk(0),
              iolist_to_binary(lists:reverse(Acc));
          Length when Length > Max ->
              exit({body_too_large, chunked});
          Length ->
              read_chunked_body(Max - Length, [read_chunk(Length) | Acc])
      end.
  
  %% @spec read_chunk_length() -> integer()
  %% @doc Read the length of the next HTTP chunk.
  
negative.code: %% @doc Receive the body of the HTTP request (defined by Content-Length).
  %%      Will receive up to MaxBody bytes.
  recv_body(MaxBody) ->
      % we could use a sane constant for max chunk size
      Body = stream_body(?MAX_RECV_BODY, fun
          ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) -> 
              iolist_to_binary(lists:reverse(BinAcc));
          ({Length, Bin}, {LengthAcc, BinAcc}) ->
              NewLength = Length + LengthAcc,
              if NewLength > MaxBody ->
                  exit({body_too_large, chunked});
              true -> 
                  {NewLength, [Bin | BinAcc]}
              end
          end, {0, []}, ?MAX_RECV_BODY),
      put(?SAVE_BODY, Body),
      Body.
  
  stream_body(MaxChunkSize, ChunkFun, FunState) ->
      stream_body(MaxChunkSize, ChunkFun, FunState, undefined).
      
  stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength) ->
  
      case get_header_value("expect") of
          "100-continue" ->
              start_raw_response({100, gb_trees:empty()});
          _Else ->
              ok
      end,
      case body_length() of
          undefined ->
              undefined;
          {unknown_transfer_encoding, Unknown} ->
              exit({unknown_transfer_encoding, Unknown});
          chunked ->
              % In this case the MaxBody is actually used to
              % determine the maximum allowed size of a single
              % chunk.
              stream_chunked_body(MaxChunkSize, ChunkFun, FunState);
          0 ->
              <<>>;
          Length when is_integer(Length) ->
              case MaxBodyLength of
              MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length ->
                  exit({body_too_large, content_length});
              _ ->
                  stream_unchunked_body(Length, MaxChunkSize, ChunkFun, FunState)
              end;     
          Length ->
              exit({length_not_integer, Length})
      end.
  
  
  %% @spec start_response({integer(), ioheaders()}) -> response()
  