diff --git a/docs/guide/README.md b/docs/guide/README.md
index f51d308933..79c6b8cc15 100644
--- a/docs/guide/README.md
+++ b/docs/guide/README.md
@@ -49,9 +49,9 @@ Handling Requests
* [Overview](runtime-overview.md)
* [Bootstrapping](runtime-bootstrapping.md)
-* **TBD** [Routing](runtime-routing.md)
-* **TBD** [Requests](runtime-requests.md)
-* **TBD** [Responses](runtime-responses.md)
+* [Routing](runtime-routing.md)
+* [Requests](runtime-requests.md)
+* [Responses](runtime-responses.md)
* **TBD** [Sessions and Cookies](runtime-sessions-cookies.md)
* [URL Parsing and Generation](runtime-url-handling.md)
* [Handling Errors](runtime-handling-errors.md)
@@ -152,7 +152,7 @@ Testing
-------
* [Overview](test-overview.md)
-* [Testing environment setup](test-endvironment-setup.md)
+* [Testing environment setup](test-environment-setup.md)
* [Unit Tests](test-unit.md)
* [Functional Tests](test-functional.md)
* [Acceptance Tests](test-acceptance.md)
diff --git a/docs/guide/runtime-requests.md b/docs/guide/runtime-requests.md
new file mode 100644
index 0000000000..fb74091efe
--- /dev/null
+++ b/docs/guide/runtime-requests.md
@@ -0,0 +1,139 @@
+Requests
+========
+
+Requests made to an application are represented in terms of [[yii\web\Request]] objects which provide information
+such as request parameters, HTTP headers, cookies, etc. For a given request, you can get access to the corresponding
+request object via the `request` [application component](structure-application-components.md). In this section,
+we will describe how you can make use of this component in your applications.
+
+
+## Request Parameters
+
+To get request parameters, you can call [[yii\web\Request::get()|get()]] and [[yii\web\Request::post()|post()]] methods
+of the `request` component. They return the values of `$_GET` and `$_POST`, respectively. For example,
+
+```php
+$request = Yii::$app->request;
+
+$get = $request->get();
+// equivalent to: $get = $_GET;
+
+$id = $request->get('id');
+// equivalent to: $id = isset($_GET['id']) ? $_GET['id'] : null;
+
+$id = $request->get('id', 1);
+// equivalent to: $id = isset($_GET['id']) ? $_GET['id'] : 1;
+
+$post = $request->post();
+// equivalent to: $post = $_POST;
+
+$name = $request->post('name');
+// equivalent to: $name = isset($_POST['name']) ? $_POST['name'] : null;
+
+$name = $request->post('name', '');
+// equivalent to: $name = isset($_POST['name']) ? $_POST['name'] : '';
+```
+
+> Info: Instead of directly accessing `$_GET` and `$_POST` to retrieve the request parameters, it is recommended
+ that you get them via the `request` component like shown above. This will make writing tests easier because
+ you can create a mock request component with faked request data.
+
+When implementing [RESTful APIs](rest-quick-start.md), you often need to retrieve parameters that are submitted
+via PUT, PATCH or other [request methods](#request-methods). You can get these parameters by calling
+the [[yii\web\Request::getBodyParam()]] methods. For example,
+
+```php
+$request = Yii::$app->request;
+
+// returns all parameters
+$params = $request->bodyParams;
+
+// returns the parameter "id"
+$param = $request->getBodyParam('id');
+```
+
+> Info: Unlike `GET` parameters, parameters submitted via `POST`, `PUT`, `PATCH` etc. are sent in the request body.
+ The `request` component will parse these parameters when you access them through the methods described above.
+ You can customize the way how these parameters are parsed by configuring the [[yii\web\Request::parsers]] property.
+
+
+## Request Methods
+
+You can get the HTTP method used by the current request via the expression `Yii::$app->request->method`.
+A whole set of boolean properties are also provided for you to check if the current method is of certain type.
+For example,
+
+```php
+$request = Yii::$app->request;
+
+if ($request->isAjax) { // the request is an AJAX request }
+if ($request->isGet) { // the request method is GET }
+if ($request->isPost) { // the request method is POST }
+if ($request->isPut) { // the request method is PUT }
+```
+
+## Request URLs
+
+The `request` component provides many ways of inspecting the currently requested URL.
+
+Assuming the URL being requested is `http://example.com/admin/index.php/product?id=100`, you can get various
+parts of this URL as summarized in the following:
+
+* [[yii\web\Request::url|url]]: returns `/admin/index.php/product?id=100`, which is the URL without the host info part.
+* [[yii\web\Request::absoluteUrl|absoluteUrl]]: returns `http://example.com/admin/index.php/product?id=100`,
+ which is the whole URL including the host info part.
+* [[yii\web\Request::hostInfo|hostInfo]]: returns `http://example.com`, which is the host info part of the URL.
+* [[yii\web\Request::pathInfo|pathInfo]]: returns `/product`, which is the part after the entry script and
+ before the question mark (query string).
+* [[yii\web\Request::queryString|queryString]]: returns `id=100`, which is the part after the question mark.
+* [[yii\web\Request::baseUrl|baseUrl]]: returns `/admin`, which is the part after the host info and before
+ the entry script name.
+* [[yii\web\Request::scriptUrl|scriptUrl]]: returns `/admin/index.php`, which is the URL without path info and query string.
+* [[yii\web\Request::serverName|serverName]]: returns `example.com`, which is the host name in the URL.
+* [[yii\web\Request::serverPort|serverPort]]: returns 80, which is the port used by the Web server.
+
+
+## HTTP Headers
+
+You can get the HTTP header information through the [[yii\web\HeaderCollection|header collection]] returned
+by the [[yii\web\Request::headers]] property. For example,
+
+```php
+// $headers is an object of yii\web\HeaderCollection
+$headers = Yii::$app->request->headers;
+
+// returns the Accept header value
+$accept = $headers->get('Accept');
+
+if ($headers->has('User-Agent')) { // there is User-Agent header }
+```
+
+The `request` component also provides support for quickly accessing some commonly used headers, including
+
+* [[yii\web\Request::userAgent|userAgent]]: returns the value of the `User-Agent` header.
+* [[yii\web\Request::contentType|contentType]]: returns the value of the `Content-Type` header which indicates
+ the MIME type of the data in the request body.
+* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: returns the content MIME types acceptable by users.
+ The returned types ordered by the quality score. Types with the highest scores will be returned first.
+* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: returns the languages acceptable by users.
+ The returned languages are ordered by their preference level. The first element represents the most preferred language.
+
+If your application supports multiple languages and you want to display pages in the language that is the most preferred
+by the end user, you may use the language negotiation method [[yii\web\Request::getPreferredLanguage()]].
+This method takes a list of languages supported by your application, compares them with [[yii\web\Request::acceptableLanguages|acceptableLanguages]],
+and returns the most appropriate language.
+
+> Tip: You may also use the [[yii\filters\ContentNegotiator|ContentNegotiator]] filter to dynamically determine
+ what content type and language should be used in the response. The filter implements the content negotiation
+ on top the properties and methods described above.
+
+
+## Client Information
+
+You can get the host name and IP address of the client machine through [[yii\web\Request::userHost|userHost]]
+and [[yii\web\Request::userIP|userIP]], respectively. For example,
+
+```php
+$userHost = Yii::$app->request->userHost;
+$userIP = Yii::$app->request->userIP;
+```
diff --git a/docs/guide/runtime-responses.md b/docs/guide/runtime-responses.md
new file mode 100644
index 0000000000..e4b1896fa9
--- /dev/null
+++ b/docs/guide/runtime-responses.md
@@ -0,0 +1,258 @@
+Responses
+=========
+
+When an application finishes handling a [request](runtime-requests.md), it generates a [[yii\web\Response|response]] object
+and sends it to the end user. The response object contains information such as the HTTP status code, HTTP headers and body.
+The ultimate goal of Web application development is essentially to build such response objects upon various requests.
+
+In most cases you should mainly deal with the `response` [application component](structure-application-components.md).
+However, Yii also allows you to create your own response objects and send them to end users.
+
+In this section, we will describe how to compose and send responses to end users.
+
+
+## Status Code
+
+One of the first things you would do when building a response is to state whether the request is successfully handled.
+This is done by setting the [[yii\web\Response::statusCode]] property which can take one of the valid
+[HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html). For example, to indicate the request
+is successfully handled, you may set the status code to be 200, like the following:
+
+```php
+Yii::$app->response->statusCode = 200;
+```
+
+However, in most cases you do not need to explicitly set the status code. This is because the default value
+of [[yii\web\Response::statusCode]] is 200. And if you want to indicate the request is unsuccessful, you may
+throw an appropriate HTTP exception like the following:
+
+```php
+throw new \yii\web\NotFoundHttpException;
+```
+
+When the [error handler](runtime-handling-errors.md) catches an exception, it will extract the status code
+from the exception and assign it to the response. For the [[yii\web\NotFoundHttpException]] above, it is
+associated with the HTTP status 404. The following HTTP exceptions are predefined in Yii:
+
+* [[yi\web\BadRequestHttpException]]: status code 400.
+* [[yi\web\ConflictHttpException]]: status code 409.
+* [[yi\web\ForbiddenHttpException]]: status code 403.
+* [[yi\web\GoneHttpException]]: status code 410.
+* [[yi\web\MethodNotAllowedHttpException]]: status code 405.
+* [[yi\web\NotAcceptableHttpException]]: status code 406.
+* [[yi\web\NotFoundHttpException]]: status code 404.
+* [[yi\web\ServerErrorHttpException]]: status code 500.
+* [[yi\web\TooManyRequestsHttpException]]: status code 429.
+* [[yi\web\UnauthorizedHttpException]]: status code 401.
+* [[yi\web\UnsupportedMediaTypeHttpException]]: status code 415.
+
+If the exception that you want to throw is not among the above list, you may create one by extending
+from [[yii\web\HttpException]], or directly throw it with a status code, for example,
+
+```php
+throw new \yii\web\HttpException(402);
+```
+
+
+## HTTP Headers
+
+You can send HTTP headers by manipulating the [[yii\web\Response::headers|header collection]] in the `response` component.
+For example,
+
+```php
+$headers = Yii::$app->response->headers;
+
+// add a Pragma header. Existing Pragma headers will NOT be overwritten.
+$headers->add('Pragma', 'no-cache');
+
+// set a Pragma header. Any existing Pragma headers will be discarded.
+$headers->add('Pragma', 'no-cache');
+
+// remove Pragma header(s) and return the removed Pragma header values in array
+$values = $headers->remove('Pragma');
+```
+
+> Info: Header names are case insensitive. And the newly registered headers are not sent to the user until
+ the [[yii\web\Response::send()]] method is called.
+
+
+## Response Body
+
+Most responses should have a body which gives the content that you want to show to end users.
+
+If you already have a formatted body string, you may assign it to the [[yii\web\Response::content]] property
+of the response. For example,
+
+```php
+Yii::$app->request->content = 'hello world!';
+```
+
+If you data needs to be formatted before sending to end users, you should set both of the
+[[yii\web\Response::format|format]] and [[yii\web\Response::data|data]] properties. The [[yii\web\Response::format|format]]
+property specifies in which format should the [[yii\web\Response::data|data]] be formatted as. For example,
+
+```php
+$response = Yii::$app->request;
+$response->format = \yii\web\Response::FORMAT_JSON;
+$response->data = ['message' => 'hello world'];
+```
+
+Yii supports the following formats out of box, each implemented by a [[yii\web\ResponseFormatterInterface|formatter]] class.
+You can customize these formatters or add new ones by configuring the [[yii\web\Response::formatters]] property.
+
+* [[yii\web\Response::FORMAT_HTML|HTML]]: implemented by [[yii\web\HtmlResponseFormatter]].
+* [[yii\web\Response::FORMAT_XML|XML]]: implemented by [[yii\web\XmlResponseFormatter]].
+* [[yii\web\Response::FORMAT_JSON|JSON]]: implemented by [[yii\web\JsonResponseFormatter]].
+* [[yii\web\Response::FORMAT_JSONP|JSONP]]: implemented by [[yii\web\JsonResponseFormatter]].
+
+While response body can be set explicitly as shown above, in most cases you may set it implicitly by the return value
+of [action](structure-controllers.md) methods. A common use case is like the following:
+
+```php
+public function actionIndex()
+{
+ return $this->render('index');
+}
+```
+
+The `index` action above returns the rendering result of the `index` view. The return value will be taken
+by the `response` component, formatted and then sent to end users.
+
+Because by default, the response format is as [[yii\web\Response::FORMAT_HTML|HTML]], you should only return a string
+in an action method. If you want to use a different response format, you should set it first before returning the data.
+For example,
+
+```php
+public function actionInfo()
+{
+ \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+ return [
+ 'message' => 'hello world',
+ 'code' => 100,
+ ];
+}
+```
+
+As aforementioned, besides using the default `response` application component, you can also create your own
+response objects and send them to end users. You can do so by returning such an object in an action method, like the following,
+
+```php
+public function actionInfo()
+{
+ return \Yii::createObject([
+ 'class' => 'yii\web\Response',
+ 'format' => \yii\web\Response::FORMAT_JSON,
+ 'data' => [
+ 'message' => 'hello world',
+ 'code' => 100,
+ ],
+ ]);
+}
+```
+
+> Note: If you are creating your own response objects, you will not be able to take advantage of the configurations
+ that you set for the `response` component in the application configuration. You can, however, use
+ [dependency injection](concept-di-container.md) to apply common configuration to your new response objects.
+
+
+## Browser Redirection
+
+Browser redirection relies on sending a `Location` HTTP header. Because this feature is commonly used, Yii provides
+some special supports for it.
+
+You can redirect the user browser to a URL by calling the [[yii\web\Response::redirect()]] method. The method
+sets the appropriate `Location` header with the given URL and returns the response object itself. In an action method,
+you can call its shortcut version [[yii\web\Controller::redirect()]]. For example,
+
+```php
+public function actionOld()
+{
+ return $this->redirect('http://example.com/new', 301);
+}
+```
+
+In the above code, the action method returns the result of the `redirect()` method. As explained before, the response
+object returned by an action method will be used as the response sending to end users.
+
+In places other than an action method, you should call [[yii\web\Response::redirect()]] directly followed by
+a call to the [[yii\web\Response::send()]] method to ensure no extra content will be appended to the response.
+
+```php
+\Yii::$app->response->redirect('http://example.com/new', 301)->send();
+```
+
+> Info: By default, the [[yii\web\Response::redirect()]] method sets the response status code to be 302 which instructs
+ the browser that the resource being requested is *temporarily* located in a different URI. You can pass in a status
+ code 301 to tell the browser that the resource has been *permanently* relocated.
+
+When the current request is an AJAX request, sending a `Location` header will not automatically cause the browser
+redirection. To solve this problem, the [[yii\web\Response::redirect()]] method sets an `X-Redirect` header with
+the redirection URL as its value. On the client side you may write JavaScript code to read this header value and
+redirect the browser accordingly.
+
+> Info: Yii comes with a `yii.js` JavaScript file which provides a set of commonly used JavaScript utilities,
+ including browser redirection based on the `X-Redirect` header. Therefore, if you are using this JavaScript file
+ (by registering the [[yii\web\YiiAsset]] asset bundle), you do not need to write anything to support AJAX redirection.
+
+
+## Sending Files
+
+Like browser redirection, file sending is another feature that relies on specific HTTP headers. Yii provides
+a set of methods to support various file sending needs. They all have built-in support for HTTP range header.
+
+* [[yii\web\Response::sendFile()]]: sends an existing file to client.
+* [[yii\web\Response::sendContentAsFile()]]: sends a text string as a file to client.
+* [[yii\web\Response::sendStreamAsFile()]]: sends an existing file stream as a file to client.
+
+These methods have the same method signature with the response object as the return value. If the file
+to be sent is very big, you should consider using [[yii\web\Response::sendStreamAsFile()]] because it is more
+memory efficient. The following example shows how to send a file in a controller action:
+
+```php
+public function actionDownload()
+{
+ return \Yii::$app->response->sendFile('path/to/file.txt');
+}
+```
+
+If you are calling the file sending method in places other than an action method, you should also call
+the [[yii\web\Response::send()]] method afterwards to ensure no extra content will be appended to the response.
+
+```php
+\Yii::$app->response->sendFile('path/to/file.txt')->send();
+```
+
+Some Web servers have a special file sending support called *X-Sendfile*. The idea is to redirect the
+request for a file to the Web server which will directly serve the file. As a result, the Web application
+can terminate earlier while the Web server is sending the file. To use this feature, you may call
+the [[yii\web\Response::xSendFile()]]. The following list summarizes how to enable the `X-Sendfile` feature
+for some popular Web servers:
+
+- Apache: [X-Sendfile](http://tn123.org/mod_xsendfile)
+- Lighttpd v1.4: [X-LIGHTTPD-send-file](http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file)
+- Lighttpd v1.5: [X-Sendfile](http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file)
+- Nginx: [X-Accel-Redirect](http://wiki.nginx.org/XSendfile)
+- Cherokee: [X-Sendfile and X-Accel-Redirect](http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile)
+
+
+## Sending Response
+
+The content in a response is not sent to the user until the [[yii\web\Response::send()]] method is called.
+By default, this method will be called automatically at the end of [[yii\base\Application::run()]]. You can, however,
+explicitly call this method to force sending out the response immediately.
+
+The [[yii\web\Response::send()]] method takes the following steps to send out a response:
+
+1. Trigger the [[yii\web\Response::EVENT_BEFORE_SEND]] event.
+2. Call [[yii\web\Response::prepare()]] to format [[yii\web\Response::data|response data]] into
+ [[yii\web\Response::content|response content]].
+3. Trigger the [[yii\web\Response::EVENT_AFTER_PREPARE]] event.
+4. Call [[yii\web\Response::sendHeaders()]] to send out the registered HTTP headers.
+5. Call [[yii\web\Response::sendContent()]] to send out the response body content.
+6. Trigger the [[yii\web\Response::EVENT_AFTER_SEND]] event.
+
+After the [[yii\web\Response::send()]] method is called once, any further call to this method will be ignored.
+This means once the response is sent out, you will not be able to append more content to it.
+
+As you can see, the [[yii\web\Response::send()]] method triggers several useful events. By responding to
+these events, it is possible to adjust or decorate the response.
diff --git a/docs/internals/translation-status.md b/docs/internals/translation-status.md
index ecad04daf6..d057ed84f5 100644
--- a/docs/internals/translation-status.md
+++ b/docs/internals/translation-status.md
@@ -28,8 +28,8 @@ structure-extensions.md | Yes
runtime-overview.md | Yes
runtime-bootstrapping.md | Yes
runtime-routing.md | Yes
-runtime-requests.md |
-runtime-responses.md |
+runtime-requests.md | Yes
+runtime-responses.md | Yes
runtime-sessions-cookies.md |
runtime-url-handling.md |
runtime-handling-errors.md |
diff --git a/framework/web/HeaderCollection.php b/framework/web/HeaderCollection.php
index 4642fd792d..39a22b3dfb 100644
--- a/framework/web/HeaderCollection.php
+++ b/framework/web/HeaderCollection.php
@@ -142,7 +142,7 @@ class HeaderCollection extends Object implements \IteratorAggregate, \ArrayAcces
/**
* Removes a header.
* @param string $name the name of the header to be removed.
- * @return string the value of the removed header. Null is returned if the header does not exist.
+ * @return array the value of the removed header. Null is returned if the header does not exist.
*/
public function remove($name)
{
@@ -150,7 +150,6 @@ class HeaderCollection extends Object implements \IteratorAggregate, \ArrayAcces
if (isset($this->_headers[$name])) {
$value = $this->_headers[$name];
unset($this->_headers[$name]);
-
return $value;
} else {
return null;