NAME
TUWF::Response - Response generation methods for TUWF
DESCRIPTION
This module is used to generate a HTTP response. It is automatically loaded by TUWF and its methods can be used without requiring any special work.
This module can not be used outside of the TUWF framework.
METHODS
The following methods are added to the main TUWF object:
resInit()
Initializes or resets the response data. All headers, cookies and content will be reset to their defaults. This method is called at the start of each request by TUWF, but it can also be useful in your own code:
# create a response, setting headers and content, etc...
tuwf->resCookie(userid => $user);
print { tuwf->resFd() } "Content!\n";
# when you later decide that you actually wanted to create a totally
# different response:
tuwf->resInit();
# ...after which you can start again
resHeader(name, value, add)
When only the name argument is present, returns the list of values of the named header in list context, or the first value in scalar context. An empty list or undef is returned if the named response header has not been set.
When name is given and value is undef
, all set headers with that name will be removed from the response.
When name and value are both given, the named header will be set to the value, possibly overwriting an earlier header of the same name. When add is also given and set to a true value, the header will be added, without potentially overwriting a previous value.
The default header (as set by reqInit()
) is:
Content-Type: text/html; charset=UTF-8
A Content-Encoding
header may be set by resBuffer()
. A Content-Length
header is added automatically when the response is sent. Set-Cookie
headers set by resCookie()
are not manipulated through this function.
TIP: When setting the Content-Type
header to a textual type, do not forget to indicate that the charset is UTF-8.
resCookie(name, value, %options)
Add and manipulate Set-Cookie
response headers. When only name is given or when value is undef
, the named cookie will be removed. That is, there will be a Set-Cookie
header telling the browser to remove the cookie. When value is also defined, the cookie will be set to that value, possibly overwriting a previous value. The following additional options are accepted:
- expires
-
A UNIX timestamp indicating when this cookie should expire. A value before the current
time()
means the cookie should be immediately removed, which is equivalent to setting value to undef. - domain
-
The domain name for which this cookie should be used.
- path
-
The absolute path for which this cookie should be present.
- secure
-
Set to true to add the secure flag to the cookie. This means that the cookie will only be present if the client is connected through HTTPS.
- httponly
-
Set to true to only allow the cookie to be read using HTTP. That is, disallow the cookie to be used within Javascript.
It is possible to set defaults for these options with the cookie_defaults setting.
resBuffer(action)
Reads or manipulates the output buffer and its encoding. action can be one of the following:
- undef / empty string
-
Returns the currently used output encoding, which can be one of 'none', 'gzip' or 'deflate'.
- clear
-
Clears the output buffer, but does not modify the output encoding.
- none
-
Clears the output buffer and disables any output encoding. All data will be sent to the client as-is.
- gzip
-
Clears the output buffer and enables gzip output compression. Requires
PerlIO::gzip
. - deflate
-
Same as gzip, but does not include the gzip header. (More correctly called 'zlib'). Requires
PerlIO::gzip
. - auto
-
Automatically detect which output encoding to use. If
PerlIO::gzip
is not installed, it will use 'none'. If it is, it will choose whatever the browser requested with theAccept-Encoding
request header.
The Content-Encoding
response header is automatically set to the correct value if compression is used. reqInit()
automatically calls reqBuffer()
. The default encoding can be set with the content_encoding setting.
Note that the :utf8
IO filter is always enabled, regardless of the encoding.
resFd()
Returns the filehandle of the output buffer. The :utf8
filter is enabled on this filehandle, meaning that everything you write to it should be in Perls native unicode format. It is a bad idea to use this filehandle for anything other than writing. It is important to remember that this filehandle writes to a buffer, and its contents will not be flushed before the request has been fully processed. Since resBuffer()
creates a new filehandle each time it is called, the return value of resFd()
is invalid after a call to resBuffer()
.
You rarely have to use this filehandle directly. TUWF::XML provides a more convenient set of functions, including lit()
, which can be used to output raw text.
resStatus(code)
Gets or sets the numeric HTTP response status code.
resRedirect(location, type)
Generate a HTTP redirect to location, which should be an absolute URL or a path relative to the current domain. If type is not defined, a 301 (Moved Permanently) is used. If type is 'temp', a 307 (Temporary Redirect) or if type is 'post' a 303 (See Other) status code is used. The latter is recommended for use as response to a POST request, as it explicitely tells the browser to use a GET request for the redirect.
Compatibility note: TUWF 1.1 and earlier called resInit()
in resRedirect()
, so if you wished to send any additional headers or cookies, you had to set these after calling resRedirect()
. In TUWF versions after 1.1, you can also set headers and cookies set before calling resRedirect()
.
resJSON(data)
Sets the content type to application/json
and sends the encoded JSON object to the client.
resBinary(data)
Send binary data to the client. This method throws away any data currently written to the buffer. This method also disables output compression to prevent additional copies of the data. Make sure to set the right content type as well, for example:
tuwf->resHeader('Content-Type' => 'image/jpeg');
tuwf->resBinary($image_data);
resFile(path, filename)
Send the contents of the given file in the given path to the client. This method returns 1 if the file exists, 0 if it does not. This method ensures that only files within path are served to the client, preventing unwanted path traversal.
The Content-Type header is set according to the file extension of filename and the mime_types and mime_default settings. You can always override this by calling resHeader()
after resFile()
.
Examples:
# Serve 'GET /static/x' requests from /webroot/public
TUWF::get qr{/static/(.+)} => sub {
tuwf->resFile('/webroot/public', tuwf->captures(1)) || tuwf->resNotFound;
};
# Serve a file in '/webroot/public' if it exists,
# otherwise handle the request as usual.
TUWF::hook before => sub {
tuwf->done if tuwf->resFile('/webroot/public', tuwf->reqPath);
};
You might also want to set proper caching headers if the static files don't change much:
tuwf->resHeader('Cache-Control' => 'max-age=31536000');
resFile()
uses resBinary()
internally, so output compression will be disabled for these files. Furthermore, this method is not really suitable for sending large files, as the entire files contents will be copied into RAM. Range requests, If-Modified-Since, ETag and such are also not supported. If any of this is a concern, it's recommended to configure your webserver to serve static files directly - without involvement of TUWF.
WARNING: The path argument should not be dependent on any input data from the client, or you might still make yourself vulnerable to path traversal!
WARNING#2: This method will follow symlinks, so you have to ensure that there are no malicious symlinks inside path. If, in the above example, there is a symlink from /webroot/public/malicious to /, then anyone will be able to retrieve any file on your system!
resNotFound()
Return a 404 Page Not Found response. The response will be exactly the same as the 404 response used when the path did not match any of the registered URI handles. This means the callback configured with error_404_handler will be called.
Important: Do NOT call this function from your error_404_handler
function, this will cause infinite recursion!
SEE ALSO
COPYRIGHT
Copyright (c) 2008-2018 Yoran Heling.
This module is part of the TUWF framework and is free software available under the liberal MIT license. See the COPYING file in the TUWF distribution for the details.
AUTHOR
Yoran Heling <projects@yorhel.nl>