anchor.diff:  %% @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,
  -    Body = case body_length() of
  -               undefined ->
  -                   undefined;
  -               {unknown_transfer_encoding, Unknown} ->
  -                   exit({unknown_transfer_encoding, Unknown});
  -               chunked ->
  -                   read_chunked_body(MaxBody, []);
  -               0 ->
  -                   <<>>;
  -               Length when is_integer(Length), Length =< MaxBody ->
  -                   recv(Length);
  -               Length ->
  -                   exit({body_too_large, Length})
  -           end,
  -    put(?SAVE_BODY, Body),
  -    Body.
  +    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()
  
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:             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) ->
  