I'm developing a web RESTful API using slim framework of php.I want to know how do I add some annotation type thing on POST method so that it can behave as URL encoded method.Please help me in this regard.Advance thanks.
There is no pre-programmed way for this - there is no Slim or php method that will definitively check if your string is urlencoded. What you can do is implement Slim Middleware to your route.
<?php
$app = new \Slim\App();
$mw = function ($request, $response, $next) {
if ( urlencode(urldecode($data)) === $data){
$response = $next($request, $response);
} else {
$response = ... // throw error
}
return $response;
};
$app->get('/', function ($request, $response, $args) { // Your route
$response->getBody()->write(' Hello ');
return $response;
})->add($mw); // chained middleware
$app->run();
Discussion: Test if string is URL encoded in PHP
Middleware: https://www.slimframework.com/docs/v3/concepts/middleware.html
Since you're using Slim as the foundation to your API, the easiest way is to just build a GET route with the desired URL parameters defined:
$app->get('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
// Route actions here
});
In your documentation, make sure you inform the consumers of this API that it is a GET endpoint, so that a POST body should not be made; rather, the parameters that you outline in the URL should be used to pass the client's data over to the API.
If you are intent on using a POST route with just URL parameters, then you could also force a response back if the route detects an incoming POST body:
$app->post('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
$postBody = $request->getParsedBody();
if (is_array($postBody)) {
$denyMsg = "This endpoint does not accept POST body as a means to transmit data; please refer to the API documentation for proper usage.";
$denyResponse = $response->withJson($denyMsg, $status = null, $encodingOptions = 0);
return $profileData;
}
});
Related
I'm using the PHP Slim Framework v3 to make a web app and the routes I have are all typically divided into either a frontend route or an API endpoint. I have a frontend route where I want to call an API endpoint to get data to display. For example:
Frontend Route
$app->get('/order/{order-id}', function(Request $request, Response $response, array $args) {
$order_id = intval($args['order-id']);
$order_details = ______; // API endpoint call to get the order details
$response = $this->view->render($response, 'order-details.html', [
'order_details' => $order_details
]);
return $response;
});
API Endpoint
$app->get('/api/order/{order-id}', function(Request $request, Response $response, array $args) use ($db) {
$order_id = intval($args['order-id']);
$order_details = $db->order_details($order_id); // Query the database for all the order details
$response = $response->withJson($order_details);
return $response;
});
What can I put in place of the ______ so I can grab the JSON being returned by the /api/order/{order-id} call?
Please note that I'm considering using Guzzle to do this, but I feel like that's such an overkill for what I'm trying to do here. I would like to think that Slim already has a way for me to do what I'm attempting to achieve.
From trying a few solutions out, I was able to use subRequest() for this:
$app->get('/order/{order-id}', function(Request $request, Response $response, array $args) use ($app) {
$order_id = intval($args['order-id']);
$order_details = $app->subRequest('GET', '/api/order/' . $order_id)->getBody(); // API endpoint call to get the order details
$order_details = json_decode($order_details);
$response = $this->view->render($response, 'order-details.html', [
'order_details' => $order_details
]);
return $response;
});
Seems to work for me, but this may not be the best solution as I am still just learning how to use Slim. Other better answers are welcome!
I'm new in Slim Framework 3. I have a problem to accessing web service that has a Api Key header value. I have had a Api Key value and wanna access the web service to get JSON data. Here is my slim get method code:
$app->get('/getbooking/{id}', function (Request $request, Response $response, $args) {
$id = $args['id'];
$string = file_get_contents('http://maindomain.com/webapi/user/'.$id);
//Still confuse how to set header value to access the web service with Api Key in the header included.
});
I have tried the web service in Postman (chrome app) to access and I get the result. I use GET method and set Headers value for Api Key.
But how to set Headers value in Slim 3 to get access the web service?
Thanks for advance :)
This doesn't actually have anything to do with Slim. There are multiple ways to make an HTTP request from within PHP including streams (file_get_contents()), curl and libraries such as Guzzle.
Your example uses file_get_contents(), so to set a header there, you need to create a context. Something like this:
$app->get('/getbooking/{id}', function (Request $request, Response $response, $args) {
$id = $args['id']; // validate $id here before using it!
// add headers. Each one is separated by "\r\n"
$options['http']['header'] = 'Authorization: Bearer {token here}';
$options['http']['header'] .= "\r\nAccept: application/json";
// create context
$context = stream_context_create($options);
// make API request
$string = file_get_contents('http://maindomain.com/webapi/user/'.$id, 0, $context);
if (false === $string) {
throw new \Exception('Unable to connect');
}
// get the status code
$status = null;
if (preg_match('#HTTP/[0-9\.]+\s+([0-9]+)#', $http_response_header[0], $matches)) {
$status = (int)$matches[1];
}
// check status code and process $string here
}
I am using Slim Framework 3 to make a small internal API to get fetch facebook data. There is about 30 specific users which have access to the API.
I want to authenticate a user by a user token send from the website, and that token is to be checked before the app is run.
The token on the user is set in the DB and when the user is requesting the API a token is send with a GET and if there is a match on the DB and the GET token, the user should be granted access to the API, otherwise the user should be forbidden to access.
I am using this to get facebook data:
$app->get('/fbdata/campaign/{campaign}/bankarea/{bankarea}/from/{from}/to/{to}/utoken/{utoken}', function(Request $request, Response $response) {
$bd = new BankAppData();
$getFb = new GetFacebookData();
$bankarea = $request->getAttribute('bankarea');
$campaign = $request->getAttribute('campaign');
$appid = $bd->BankData($bankarea)->appid;
$appsecret = $bd->BankData($bankarea)->appsecret;
$fbtoken = $bd->BankData($bankarea)->fbtoken;
$dateFrom = $request->getAttribute('from');
$dateTo = $request->getAttribute('to');
$getFb->FetchData($appid, $appsecret, $fbtoken, $campaign, $bankarea, "act_XXXX", $dateFrom, $dateTo);
});
This works just fine, but I want to use a AuthenticationHandler class for checking the utoken before the above is run.
I am adding it by using $app->add(new SNDB\AuthenticationHandler()); but I am unsure on how I can get the utoken from the URL in my AuthenticationHandler class.
Basically I want to do something like
function Authenticate() {
if($dbToken != $utoken) {
//No access - app will just stop doing anything else
} else {
//You have access - just continue what you was trying to do
}
}
You should take a look at the middleware concept from slim3.
Basically there are 2 options how to add middleware:
per anonymous function
$app->add(function ($request, $response, $next) {
$response->getBody()->write('BEFORE');
$response = $next($request, $response);
$response->getBody()->write('AFTER');
return $response;
});
per invokable class
class ExampleMiddleware
{
public function __invoke($request, $response, $next)
{
$response->getBody()->write('BEFORE');
$response = $next($request, $response);
$response->getBody()->write('AFTER');
return $response;
}
}
$app->add(new ExampleMiddleware);
There you have the PSR-7 request and can get your utoken from the url.
I'm trying to integrate a decoupled wordpress/wp-api to a Slim 3 framework with Twig views.
Ideally I want to send all posts to /posts route rendered via Twig and
Individual posts to /post/hello-world route
I'm having two issues for now:
I want to pass the response back (queried via guzzle) to a Twig view and I'm struggling with that.
The JSON response I'm getting back in the view is not an appropriate JSON response when I echo $body;
// ROUTES
$app->get('/', function ($request, $response) {
return $this->view->render($response, 'home.html');
})->setName('home');
$app->get('/posts/', function ($request, $response,array $args) {
$client = new Client();
$url ='/cms/wp-json/wp/v2/posts';
$res = $client->request('GET',$url,array(
'content-type' => 'application/json'
),array());
$body = $res->getBody();
// echo $body;
return $this->view->render( $response,'posts.html',array('posts' => $body));
})->setName('posts');
I would really like to keep using Twig with Slim instead of using Vue.js or Angular and build a SPA.
I have users getting auto-generated when they login via social media. I don't get their email so I want to make it that when they land on /whatever/page/after/login they see a screen that's like "Just enter email to continue on!"
I took a look at http://silex.sensiolabs.org/doc/cookbook/sub_requests.html and I'm either misreading or thinking I'd need to do it within a Silex\ControllerProviderInterface. I want this behavior to be for any request. Meanwhile if I make all my providers extend one, I'm not sure of the right way to cut out of a parent's connect without botching everything.
I also tried re-initializing everything similar to the answer here Unable to overwrite pathInfo in a Symfony 2 Request.
Here is the code I'm working with:
$app
->before(function (Request $request) use ($app) {
$token = $app['security']->getToken();
$app['user'] = null;
if ($token && !$app['security.trust_resolver']->isAnonymous($token)) {
$app['user'] = $token->getUser();
if (!$app['user']->isVerified()) {
$request->server->set('REQUEST_URI', '/signup');
$request->initialize($request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all(), $request->getContent());
}
}
});
I believe what you want to do is create a new Request object with the correct values and then tell that app to handle it.
If you don't care about preserving the request params from the original request then you can strip a lot of the extra stuff out.
$app
->before(function (Request $request) use ($app) {
$token = $app['security']->getToken();
$app['user'] = null;
if ($token && !$app['security.trust_resolver']->isAnonymous($token)) {
$app['user'] = $token->getUser();
if (!$app['user']->isVerified()) {
$subRequest = Request::create('/signup', 'GET', $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all(), $request->getContent());
$subRequest->request = $request->request;
$subRequest->query = $request->query;
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
}
});