xref: /plugin/davcal/vendor/sabre/http/lib/Response.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\HTTP;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehler/**
6*a1a3b679SAndreas Boehler * This class represents a single HTTP response.
7*a1a3b679SAndreas Boehler *
8*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2009-2015 fruux GmbH (https://fruux.com/).
9*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
10*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
11*a1a3b679SAndreas Boehler */
12*a1a3b679SAndreas Boehlerclass Response extends Message implements ResponseInterface {
13*a1a3b679SAndreas Boehler
14*a1a3b679SAndreas Boehler    /**
15*a1a3b679SAndreas Boehler     * This is the list of currently registered HTTP status codes.
16*a1a3b679SAndreas Boehler     *
17*a1a3b679SAndreas Boehler     * @var array
18*a1a3b679SAndreas Boehler     */
19*a1a3b679SAndreas Boehler    static $statusCodes = [
20*a1a3b679SAndreas Boehler        100 => 'Continue',
21*a1a3b679SAndreas Boehler        101 => 'Switching Protocols',
22*a1a3b679SAndreas Boehler        102 => 'Processing',
23*a1a3b679SAndreas Boehler        200 => 'OK',
24*a1a3b679SAndreas Boehler        201 => 'Created',
25*a1a3b679SAndreas Boehler        202 => 'Accepted',
26*a1a3b679SAndreas Boehler        203 => 'Non-Authorative Information',
27*a1a3b679SAndreas Boehler        204 => 'No Content',
28*a1a3b679SAndreas Boehler        205 => 'Reset Content',
29*a1a3b679SAndreas Boehler        206 => 'Partial Content',
30*a1a3b679SAndreas Boehler        207 => 'Multi-Status', // RFC 4918
31*a1a3b679SAndreas Boehler        208 => 'Already Reported', // RFC 5842
32*a1a3b679SAndreas Boehler        226 => 'IM Used', // RFC 3229
33*a1a3b679SAndreas Boehler        300 => 'Multiple Choices',
34*a1a3b679SAndreas Boehler        301 => 'Moved Permanently',
35*a1a3b679SAndreas Boehler        302 => 'Found',
36*a1a3b679SAndreas Boehler        303 => 'See Other',
37*a1a3b679SAndreas Boehler        304 => 'Not Modified',
38*a1a3b679SAndreas Boehler        305 => 'Use Proxy',
39*a1a3b679SAndreas Boehler        307 => 'Temporary Redirect',
40*a1a3b679SAndreas Boehler        308 => 'Permanent Redirect',
41*a1a3b679SAndreas Boehler        400 => 'Bad Request',
42*a1a3b679SAndreas Boehler        401 => 'Unauthorized',
43*a1a3b679SAndreas Boehler        402 => 'Payment Required',
44*a1a3b679SAndreas Boehler        403 => 'Forbidden',
45*a1a3b679SAndreas Boehler        404 => 'Not Found',
46*a1a3b679SAndreas Boehler        405 => 'Method Not Allowed',
47*a1a3b679SAndreas Boehler        406 => 'Not Acceptable',
48*a1a3b679SAndreas Boehler        407 => 'Proxy Authentication Required',
49*a1a3b679SAndreas Boehler        408 => 'Request Timeout',
50*a1a3b679SAndreas Boehler        409 => 'Conflict',
51*a1a3b679SAndreas Boehler        410 => 'Gone',
52*a1a3b679SAndreas Boehler        411 => 'Length Required',
53*a1a3b679SAndreas Boehler        412 => 'Precondition failed',
54*a1a3b679SAndreas Boehler        413 => 'Request Entity Too Large',
55*a1a3b679SAndreas Boehler        414 => 'Request-URI Too Long',
56*a1a3b679SAndreas Boehler        415 => 'Unsupported Media Type',
57*a1a3b679SAndreas Boehler        416 => 'Requested Range Not Satisfiable',
58*a1a3b679SAndreas Boehler        417 => 'Expectation Failed',
59*a1a3b679SAndreas Boehler        418 => 'I\'m a teapot', // RFC 2324
60*a1a3b679SAndreas Boehler        421 => 'Misdirected Request', // RFC7540 (HTTP/2)
61*a1a3b679SAndreas Boehler        422 => 'Unprocessable Entity', // RFC 4918
62*a1a3b679SAndreas Boehler        423 => 'Locked', // RFC 4918
63*a1a3b679SAndreas Boehler        424 => 'Failed Dependency', // RFC 4918
64*a1a3b679SAndreas Boehler        426 => 'Upgrade Required',
65*a1a3b679SAndreas Boehler        428 => 'Precondition Required', // RFC 6585
66*a1a3b679SAndreas Boehler        429 => 'Too Many Requests', // RFC 6585
67*a1a3b679SAndreas Boehler        431 => 'Request Header Fields Too Large', // RFC 6585
68*a1a3b679SAndreas Boehler        451 => 'Unavailable For Legal Reasons', // draft-tbray-http-legally-restricted-status
69*a1a3b679SAndreas Boehler        500 => 'Internal Server Error',
70*a1a3b679SAndreas Boehler        501 => 'Not Implemented',
71*a1a3b679SAndreas Boehler        502 => 'Bad Gateway',
72*a1a3b679SAndreas Boehler        503 => 'Service Unavailable',
73*a1a3b679SAndreas Boehler        504 => 'Gateway Timeout',
74*a1a3b679SAndreas Boehler        505 => 'HTTP Version not supported',
75*a1a3b679SAndreas Boehler        506 => 'Variant Also Negotiates',
76*a1a3b679SAndreas Boehler        507 => 'Insufficient Storage', // RFC 4918
77*a1a3b679SAndreas Boehler        508 => 'Loop Detected', // RFC 5842
78*a1a3b679SAndreas Boehler        509 => 'Bandwidth Limit Exceeded', // non-standard
79*a1a3b679SAndreas Boehler        510 => 'Not extended',
80*a1a3b679SAndreas Boehler        511 => 'Network Authentication Required', // RFC 6585
81*a1a3b679SAndreas Boehler    ];
82*a1a3b679SAndreas Boehler
83*a1a3b679SAndreas Boehler    /**
84*a1a3b679SAndreas Boehler     * HTTP status code
85*a1a3b679SAndreas Boehler     *
86*a1a3b679SAndreas Boehler     * @var int
87*a1a3b679SAndreas Boehler     */
88*a1a3b679SAndreas Boehler    protected $status;
89*a1a3b679SAndreas Boehler
90*a1a3b679SAndreas Boehler    /**
91*a1a3b679SAndreas Boehler     * HTTP status text
92*a1a3b679SAndreas Boehler     *
93*a1a3b679SAndreas Boehler     * @var string
94*a1a3b679SAndreas Boehler     */
95*a1a3b679SAndreas Boehler    protected $statusText;
96*a1a3b679SAndreas Boehler
97*a1a3b679SAndreas Boehler    /**
98*a1a3b679SAndreas Boehler     * Creates the response object
99*a1a3b679SAndreas Boehler     *
100*a1a3b679SAndreas Boehler     * @param string|int $status
101*a1a3b679SAndreas Boehler     * @param array $headers
102*a1a3b679SAndreas Boehler     * @param resource $body
103*a1a3b679SAndreas Boehler     * @return void
104*a1a3b679SAndreas Boehler     */
105*a1a3b679SAndreas Boehler    function __construct($status = null, array $headers = null, $body = null) {
106*a1a3b679SAndreas Boehler
107*a1a3b679SAndreas Boehler        if (!is_null($status)) $this->setStatus($status);
108*a1a3b679SAndreas Boehler        if (!is_null($headers)) $this->setHeaders($headers);
109*a1a3b679SAndreas Boehler        if (!is_null($body)) $this->setBody($body);
110*a1a3b679SAndreas Boehler
111*a1a3b679SAndreas Boehler    }
112*a1a3b679SAndreas Boehler
113*a1a3b679SAndreas Boehler
114*a1a3b679SAndreas Boehler    /**
115*a1a3b679SAndreas Boehler     * Returns the current HTTP status code.
116*a1a3b679SAndreas Boehler     *
117*a1a3b679SAndreas Boehler     * @return int
118*a1a3b679SAndreas Boehler     */
119*a1a3b679SAndreas Boehler    function getStatus() {
120*a1a3b679SAndreas Boehler
121*a1a3b679SAndreas Boehler        return $this->status;
122*a1a3b679SAndreas Boehler
123*a1a3b679SAndreas Boehler    }
124*a1a3b679SAndreas Boehler
125*a1a3b679SAndreas Boehler    /**
126*a1a3b679SAndreas Boehler     * Returns the human-readable status string.
127*a1a3b679SAndreas Boehler     *
128*a1a3b679SAndreas Boehler     * In the case of a 200, this may for example be 'OK'.
129*a1a3b679SAndreas Boehler     *
130*a1a3b679SAndreas Boehler     * @return string
131*a1a3b679SAndreas Boehler     */
132*a1a3b679SAndreas Boehler    function getStatusText() {
133*a1a3b679SAndreas Boehler
134*a1a3b679SAndreas Boehler        return $this->statusText;
135*a1a3b679SAndreas Boehler
136*a1a3b679SAndreas Boehler    }
137*a1a3b679SAndreas Boehler
138*a1a3b679SAndreas Boehler    /**
139*a1a3b679SAndreas Boehler     * Sets the HTTP status code.
140*a1a3b679SAndreas Boehler     *
141*a1a3b679SAndreas Boehler     * This can be either the full HTTP status code with human readable string,
142*a1a3b679SAndreas Boehler     * for example: "403 I can't let you do that, Dave".
143*a1a3b679SAndreas Boehler     *
144*a1a3b679SAndreas Boehler     * Or just the code, in which case the appropriate default message will be
145*a1a3b679SAndreas Boehler     * added.
146*a1a3b679SAndreas Boehler     *
147*a1a3b679SAndreas Boehler     * @param string|int $status
148*a1a3b679SAndreas Boehler     * @throws \InvalidArgumentExeption
149*a1a3b679SAndreas Boehler     * @return void
150*a1a3b679SAndreas Boehler     */
151*a1a3b679SAndreas Boehler    function setStatus($status) {
152*a1a3b679SAndreas Boehler
153*a1a3b679SAndreas Boehler        if (ctype_digit($status) || is_int($status)) {
154*a1a3b679SAndreas Boehler
155*a1a3b679SAndreas Boehler            $statusCode = $status;
156*a1a3b679SAndreas Boehler            $statusText = isset(self::$statusCodes[$status]) ? self::$statusCodes[$status] : 'Unknown';
157*a1a3b679SAndreas Boehler
158*a1a3b679SAndreas Boehler        } else {
159*a1a3b679SAndreas Boehler            list(
160*a1a3b679SAndreas Boehler                $statusCode,
161*a1a3b679SAndreas Boehler                $statusText
162*a1a3b679SAndreas Boehler            ) = explode(' ', $status, 2);
163*a1a3b679SAndreas Boehler        }
164*a1a3b679SAndreas Boehler        if ($statusCode < 100 || $statusCode > 999) {
165*a1a3b679SAndreas Boehler            throw new \InvalidArgumentException('The HTTP status code must be exactly 3 digits');
166*a1a3b679SAndreas Boehler        }
167*a1a3b679SAndreas Boehler
168*a1a3b679SAndreas Boehler        $this->status = $statusCode;
169*a1a3b679SAndreas Boehler        $this->statusText = $statusText;
170*a1a3b679SAndreas Boehler
171*a1a3b679SAndreas Boehler    }
172*a1a3b679SAndreas Boehler
173*a1a3b679SAndreas Boehler    /**
174*a1a3b679SAndreas Boehler     * Serializes the response object as a string.
175*a1a3b679SAndreas Boehler     *
176*a1a3b679SAndreas Boehler     * This is useful for debugging purposes.
177*a1a3b679SAndreas Boehler     *
178*a1a3b679SAndreas Boehler     * @return string
179*a1a3b679SAndreas Boehler     */
180*a1a3b679SAndreas Boehler    function __toString() {
181*a1a3b679SAndreas Boehler
182*a1a3b679SAndreas Boehler        $str = 'HTTP/' . $this->httpVersion . ' ' . $this->getStatus() . ' ' . $this->getStatusText() . "\r\n";
183*a1a3b679SAndreas Boehler        foreach ($this->getHeaders() as $key => $value) {
184*a1a3b679SAndreas Boehler            foreach ($value as $v) {
185*a1a3b679SAndreas Boehler                $str .= $key . ": " . $v . "\r\n";
186*a1a3b679SAndreas Boehler            }
187*a1a3b679SAndreas Boehler        }
188*a1a3b679SAndreas Boehler        $str .= "\r\n";
189*a1a3b679SAndreas Boehler        $str .= $this->getBodyAsString();
190*a1a3b679SAndreas Boehler        return $str;
191*a1a3b679SAndreas Boehler
192*a1a3b679SAndreas Boehler    }
193*a1a3b679SAndreas Boehler
194*a1a3b679SAndreas Boehler}
195