1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
<?php /** * Klein (klein.php) - A fast & flexible router for PHP * * @author Chris O'Hara <cohara87@gmail.com> * @author Trevor Suarez (Rican7) (contributor and v2 refactorer) * @copyright (c) Chris O'Hara * @link https://github.com/klein/klein.php * @license MIT */
namespace Klein;
use Klein\Exceptions\ResponseAlreadySentException; use RuntimeException;
/** * Response */ class Response extends AbstractResponse {
/** * Methods */
/** * Enable response chunking * * @link https://github.com/klein/klein.php/wiki/Response-Chunking * @link http://bit.ly/hg3gHb * @param string $str An optional string to send as a response "chunk" * @return Response */ public function chunk($str = null) { parent::chunk();
if (null !== $str) { printf("%x\r\n", strlen($str)); echo "$str\r\n"; flush(); }
return $this; }
/** * Dump a variable * * @param mixed $obj The variable to dump * @return Response */ public function dump($obj) { if (is_array($obj) || is_object($obj)) { $obj = print_r($obj, true); }
$this->append('<pre>' . htmlentities($obj, ENT_QUOTES) . "</pre><br />\n");
return $this; }
/** * Sends a file * * It should be noted that this method disables caching * of the response by default, as dynamically created * files responses are usually downloads of some type * and rarely make sense to be HTTP cached * * Also, this method removes any data/content that is * currently in the response body and replaces it with * the file's data * * @param string $path The path of the file to send * @param string $filename The file's name * @param string $mimetype The MIME type of the file * @throws RuntimeException Thrown if the file could not be read * @return Response */ public function file($path, $filename = null, $mimetype = null) { if ($this->sent) { throw new ResponseAlreadySentException('Response has already been sent'); }
$this->body(''); $this->noCache();
if (null === $filename) { $filename = basename($path); } if (null === $mimetype) { $mimetype = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path); }
$this->header('Content-type', $mimetype); $this->header('Content-Disposition', 'attachment; filename="'.$filename.'"');
// If the response is to be chunked, then the content length must not be sent // see: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 if (false === $this->chunked) { $this->header('Content-length', filesize($path)); }
// Send our response data $this->sendHeaders();
$bytes_read = readfile($path);
if (false === $bytes_read) { throw new RuntimeException('The file could not be read'); }
$this->sendBody();
// Lock the response from further modification $this->lock();
// Mark as sent $this->sent = true;
// If there running FPM, tell the process manager to finish the server request/response handling if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); }
return $this; }
/** * Sends an object as json or jsonp by providing the padding prefix * * It should be noted that this method disables caching * of the response by default, as json responses are usually * dynamic and rarely make sense to be HTTP cached * * Also, this method removes any data/content that is * currently in the response body and replaces it with * the passed json encoded object * * @param mixed $object The data to encode as JSON * @param string $jsonp_prefix The name of the JSON-P function prefix * @return Response */ public function json($object, $jsonp_prefix = null) { $this->body(''); $this->noCache();
$json = json_encode($object);
if (null !== $jsonp_prefix) { // Should ideally be application/json-p once adopted $this->header('Content-Type', 'text/javascript'); $this->body("$jsonp_prefix($json);"); } else { $this->header('Content-Type', 'application/json'); $this->body($json); }
$this->send();
return $this; } }
|