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.

maxage

Number of seconds until the cookie expires. May be used instead of or together with expires. Older browsers do not support this option.

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.

samesite

Set to 'Strict' or 'Lax' to prevent this cookie to be included in requests originating from other domains, as a measure against CSRF attacks. Set to 'None' to disable such protections.

For more information about the meaning and interpretation of those options, see the MDN documentation.

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 the Accept-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, buffer_action)

Send raw/binary data to the client. This method throws away any data currently written to the buffer. The optional buffer_action argument is passed to resBuffer() and can be used to control output compression. 'none' is assumed when absent. This method can prevent additional copies of the data when output compression is disabled.

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, output compression is only enabled if the file's mime type starts with text. 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

TUWF

COPYRIGHT

Copyright (c) 2008-2019 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>