forked from telabotanica/tb-base-rest-service-php
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBaseRestServiceTB.php
186 lines (165 loc) · 4.78 KB
/
BaseRestServiceTB.php
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<?php
/*
* Base class for REST services
* @author [email protected]
* @date 08/2015
*/
class BaseRestServiceTB {
/** Configuration given at construct time */
protected $config;
/** HTTP verb received (GET, POST, PUT, DELETE, OPTIONS) */
protected $verb;
/** Resources (URI elements) */
protected $resources = array();
/** Request parameters (GET or POST) */
protected $params = array();
/** Domain root (to build URIs) */
protected $domainRoot;
/** Base URI (to parse resources) */
protected $baseURI;
public function __construct($config) {
$this->config = $config;
// HTTP method
$this->verb = $_SERVER['REQUEST_METHOD'];
// server config
$this->domainRoot = $this->config['domain_root'];
$this->baseURI = $this->config['base_uri'];
// initialization
$this->getResources();
$this->getParams();
$this->init();
}
/** Post-constructor adjustments */
protected function init() {
}
/**
* Reads the request and runs the appropriate method; catches library
* exceptions and turns them into HTTP errors with message
*/
public function run() {
try {
switch($this->verb) {
case "GET":
$this->get();
break;
case "POST":
$this->post();
break;
case "PUT":
$this->put();
break;
case "DELETE":
$this->delete();
break;
case "OPTIONS":
// @WARNING will break CORS if you implement it
$this->options();
break;
default:
$this->sendError("unsupported method: $this->verb");
}
} catch(Exception $e) {
// catches lib exceptions and turns them into error 500
$this->sendError($e->getMessage(), 500);
}
}
/**
* Sends a JSON message indicating a success and exits the program
* @param type $json the message
* @param type $code defaults to 200 (HTTP OK)
*/
protected function sendJson($json, $code=200) {
header('Content-type: application/json');
http_response_code($code);
echo json_encode($json, JSON_UNESCAPED_UNICODE);
exit;
}
/**
* Sends a JSON message indicating an error and exits the program
* @param type $error a string explaining the reason for this error
* @param type $code defaults to 400 (HTTP Bad Request)
*/
protected function sendError($error, $code=400) {
header('Content-type: application/json');
http_response_code($code);
echo json_encode(array("error" => $error));
exit;
}
/**
* Compares request URI to base URI to extract URI elements (resources)
*/
protected function getResources() {
$uri = $_SERVER['REQUEST_URI'];
// slicing URI
$baseURI = $this->baseURI . "/";
if ((strlen($uri) > strlen($baseURI)) && (strpos($uri, $baseURI) !== false)) {
$baseUriLength = strlen($baseURI);
$posQM = strpos($uri, '?');
if ($posQM != false) {
$resourcesString = substr($uri, $baseUriLength, $posQM - $baseUriLength);
} else {
$resourcesString = substr($uri, $baseUriLength);
}
// decoding special characters
$resourcesString = urldecode($resourcesString);
//echo "Resources: $resourcesString" . PHP_EOL;
$this->resources = explode("/", $resourcesString);
// in case of a final /, gets rid of the last empty resource
$nbRessources = count($this->resources);
if (empty($this->resources[$nbRessources - 1])) {
unset($this->resources[$nbRessources - 1]);
}
}
}
/**
* Gets the GET or POST request parameters
*/
protected function getParams() {
$this->params = $_REQUEST;
}
/**
* Searches for parameter $name in $this->params; if defined (even if
* empty), returns its value; if undefined, returns $default; if
* $collection is a non-empty array, parameters will be searched among
* it rather than among $this->params (2-in-1-dirty-mode)
*/
protected function getParam($name, $default=null, $collection=null) {
$arrayToSearch = $this->params;
if (is_array($collection) && !empty($collection)) {
$arrayToSearch = $collection;
}
if (isset($arrayToSearch[$name])) {
return $arrayToSearch[$name];
} else {
return $default;
}
}
/**
* Reads and returns request body contents
*/
protected function readRequestBody() {
// @TODO beware of memory consumption
$contents = file_get_contents('php://input');
return $contents;
}
protected function sendFile($file, $name, $size, $mimetype='application/octet-stream') {
if (! file_exists($file)) {
$this->sendError("file does not exist");
}
header('Content-Type: ' . $mimetype);
header('Content-Disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $size);
// progressive sending
// http://www.media-division.com/the-right-way-to-handle-file-downloads-in-php/
set_time_limit(0);
$f = @fopen($file,"rb");
while(!feof($f)) {
print(fread($f, 1024*8));
ob_flush();
flush();
}
}
}