1%% @author Bob Ippolito <bob@mochimedia.com> 2%% @copyright 2007 Mochi Media, Inc. 3%% 4%% Permission is hereby granted, free of charge, to any person obtaining a 5%% copy of this software and associated documentation files (the "Software"), 6%% to deal in the Software without restriction, including without limitation 7%% the rights to use, copy, modify, merge, publish, distribute, sublicense, 8%% and/or sell copies of the Software, and to permit persons to whom the 9%% Software is furnished to do so, subject to the following conditions: 10%% 11%% The above copyright notice and this permission notice shall be included in 12%% all copies or substantial portions of the Software. 13%% 14%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17%% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20%% DEALINGS IN THE SOFTWARE. 21 22%% @doc Response abstraction. 23 24-module(mochiweb_response). 25-author('bob@mochimedia.com'). 26 27-define(QUIP, "Any of you quaids got a smint?"). 28 29-export([new/3, get_header_value/2, get/2, dump/1]). 30-export([send/2, write_chunk/2]). 31 32%% @type response(). A mochiweb_response parameterized module instance. 33 34%% @spec new(Request, Code, Headers) -> response() 35%% @doc Create a new mochiweb_response instance. 36new(Request, Code, Headers) -> 37 {?MODULE, [Request, Code, Headers]}. 38 39%% @spec get_header_value(string() | atom() | binary(), response()) -> 40%% string() | undefined 41%% @doc Get the value of the given response header. 42get_header_value(K, {?MODULE, [_Request, _Code, Headers]}) -> 43 mochiweb_headers:get_value(K, Headers). 44 45%% @spec get(request | code | headers, response()) -> term() 46%% @doc Return the internal representation of the given field. 47get(request, {?MODULE, [Request, _Code, _Headers]}) -> 48 Request; 49get(code, {?MODULE, [_Request, Code, _Headers]}) -> 50 Code; 51get(headers, {?MODULE, [_Request, _Code, Headers]}) -> 52 Headers. 53 54%% @spec dump(response()) -> {mochiweb_request, [{atom(), term()}]} 55%% @doc Dump the internal representation to a "human readable" set of terms 56%% for debugging/inspection purposes. 57dump({?MODULE, [Request, Code, Headers]}) -> 58 [{request, Request:dump()}, 59 {code, Code}, 60 {headers, mochiweb_headers:to_list(Headers)}]. 61 62%% @spec send(iodata(), response()) -> ok 63%% @doc Send data over the socket if the method is not HEAD. 64send(Data, {?MODULE, [Request, _Code, _Headers]}) -> 65 case Request:get(method) of 66 'HEAD' -> 67 ok; 68 _ -> 69 Request:send(Data) 70 end. 71 72%% @spec write_chunk(iodata(), response()) -> ok 73%% @doc Write a chunk of a HTTP chunked response. If Data is zero length, 74%% then the chunked response will be finished. 75write_chunk(Data, {?MODULE, [Request, _Code, _Headers]}=THIS) -> 76 case Request:get(version) of 77 Version when Version >= {1, 1} -> 78 Length = iolist_size(Data), 79 send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS); 80 _ -> 81 send(Data, THIS) 82 end. 83 84 85%% 86%% Tests 87%% 88-ifdef(TEST). 89-include_lib("eunit/include/eunit.hrl"). 90-endif. 91