SLIM PHP api 400 error - $_REQUEST not working - php

I'm beginning to learn how to properly use REST API's following a popular tutorial here
When trying to create a simple POST api I keep running into a 400 error and I haven't found any answers online as of yet.
API is as follows:
$app->post('/test', function() use ($app) {
// check for required params
verifyRequiredParams(array('email'));
echo "Success";
});
Which attempts to verify the 'email' parameter with this block of code, unchanged from the tutorial:
function verifyRequiredParams($required_fields) {
$error = false;
$error_fields = "";
$request_params = array();
$request_params = $_REQUEST;
// Handling PUT request params
if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
$app = \Slim\Slim::getInstance();
parse_str($app->request()->getBody(), $request_params);
}
foreach ($required_fields as $field) {
if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
$error = true;
$error_fields .= $field . ', ';
}
}
if ($error) {
// Required field(s) are missing or empty
// echo error json and stop the app
$response = array();
$app = \Slim\Slim::getInstance();
$response["error"] = true;
$response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
echoRespnse(400, $response);
$app->stop();
}
}
The code always fails with a 400 error code because it seems that the $_REQUEST function is returning an empty array. Any idea's what could be going wrong? I'm developing on an ubuntu server running apache.
The Slim API framework is set up correctly as I can call a very simple call through Google's Advanced Rest Client which echos a response correctly. And I am definitely passing the correct parameters into the api.
UPDATE: I've also tried running the $_REQUEST and $_GET functions directly from the api and it just returns an empty string like this:
Array
(
)
I wonder if there's some sort of apache config file that's blocking data to these functions or something?

Possible Problem:
Have you double checked that your selected Content-Type in the request headers is right?
I suspect the client is perceiving a malformed markup language being sent from the server side.
Possible Solution:
Change Content-Type: application/x-www-form-urlencoded to application/JSON or vice versa.

For the tutorial to receive
$name = $app->request->post('name');
the POST parameters have to be in Payload data
name=yourname&password=pass&email=me#mail.com
application/x-www-form-urlencoded
If you provide the parameters after the URL but not in the payload data, that is for a GET request. In such a case the tutorial partly works (it sees the parameters to verify required parameters are present) but it is looking for the parameters "anywhere" when it should only be looking in the payload parameters for POST.

Related

What does it mean if your request from postman returns HTML body?

When I send a request in postman, it returns a html body and it says 404 not found. Does this mean my php server is not running? I am trying to run my php code in visual studio code as a php server.
This is the php file:
<?php
// Headers
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include_once '../../config/Database.php';
include_once '../../models/Login.php';
// Instantiate DB & connect
$database = new Database();
$db = $database->connect();
// Instantiate blog post object
$login = new Login($db);
//$login->email=isset($_GET['username']) ? $_GET['username']:die();
$login->password=isset($_GET['phoneNumber']) ? $_GET['phoneNumber']:die();
$result = $login->read_single();
$num = $result->rowCount();
if($num > 0) {
// Post array
$posts_arr = array();
$posts_arr['data2'] = array();
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
extract($row);
$post_item = array(
//'username' => $username,
'phoneNumber' => $phoneNumber,
'token' =>$token,
'tokencreatedat'=>$tokencreatedat,
'expTime'=>$expTime
);
// Push to "data"
//array_push($posts_arr, $post_item);
array_push($posts_arr['data2'], $post_item);
}
// Turn to JSON & output
echo json_encode($posts_arr);
} else {
// No Posts
echo json_encode(
array('message' => 'No Posts Found')
);
}
?>
Plus, how do you run php as a web server for RESTful API?
UPDATE: when I put localhost:3000/path in the url in postman, it return 200 which mean its okay. But when I input the IP address, it returns 404.
404 means the url you are trying to get is not found !
as per your html,I think your api endpoints ( if you created any or not in both case) has an issue so its showing 404.
I assume you are trying to create an api for user login right ?
at first you should learn about the RESTful Api concept and how to create api endpoints.
this might help
For a quick learning:
create a login_api.php file which will contain php code only. it will take your username / password etc from _POST[], validate your user and redirect you to your home.php
This means that the api which you are hitting have some issues.
So in your case most probably you have some issues with your php laravel code, that's why whenever you are calling that api then html code was returned on behalf of that.
Moreover 404 means that api is not found but then your service is running
Please check your code for syntactical bugs.
For Restful Api's using php, you can refer this and this

How to use zend_http_client or curl in right way

I'm using zend_http_client. What i want is to send a request to transfer(without redirecting) to another site and send number in field that I have and get the answer with info i need to use on my site. That's what i'm doing, but how to send my number to that field and submit it?
$url = 'http://gdeposylka.ru/';
$config = array(
'timeout' => 30
);
$client = new Zend_Http_Client($url, $config);
try {
$response = $client->request('GET');
if ($response->getStatus() == 200) {
$ctype = $response->getHeader('Content-type');
$body = $response->getBody();
$dom = new Zend_Dom_Query($body);
$results = $dom->query('limit');
$item->site_k = 1 + (int) $results->current()->textContent;
var_dump($response);
exit;
}
} catch (Zend_Http_Client_Adapter_Exception $e) {
}
Thanks and sorry for grammar mistakes.
Because there is a hash on the site you're trying to send a request, you probably wont be able to get this done. Hash mechanism makes it impossible to send request straight to the URL stated in action param of form tag. It's designed particulary to prevent such action you want to make. Still, since there is no captcha you can try web automation.
What you might find useful is ie. Selenium http://docs.seleniumhq.org/

Unable to Simulate HTTP 302 response

I'm trying to incorporate PagSeguro (a payment gateway - Brazil's version of PayPal) into my site. After the customer finishes with PagSeguro, they send data (via POST) to a function which I specify. However, I'm not receiving the POST. After doing all the troubleshooting I could think of, I contacted PagSeguro. They said that their log indicates that the POST is being sent as normal but they are receiving an HTTP 302 response.
In order to figure out why this is happening, I created a form with hidden values to simulate sending a POST to my function. I put this form under a different domain just in case it had something to do with that. Every time I send the POST from my simulation form, I receive an HTTP 200 response, and my log indicates that the POST was received.
How is it possible that PagSeguro is receiving a different response than my simulation? Could it have something to do with the server or is it something to do with my script?
Here is the function (using CodeIgniter) that should be receiving the POST:
function pagseguro_retorno(){
if (count($_POST) == 0) {
return FALSE;
}
$msg = 'POST RECEIVED';
$simulate = $this->input->post('Simulate');
if ( ! empty($simulate)){
$result = 'VERIFICADO';
$msg .= ' FROM SIMULATOR';
} else {
$this->load->library(PagSeguroNpi);
$result = $this->PagSeguroNpi->notificationPost();
}
$this->log($msg);
if ($result == "VERIFICADO") {
$id = $this->input->post('Referencia');//cart id
$this->load->model('transacao_model');
$trans_row = $this->transacao_model->get_transaction($id);
if ( ! is_object($trans_row)){
//LOAD NEW TRANSACTION
if ( ! $this->new_transaction($id)){
$notice = "Unable to load new transaction</p><p>";
$this->log($notice);
$notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
$this->email_notice($notice);
}
}
$this->load->model('carrinho_model');
if($_POST['StatusTransacao'] == 'Aprovado'){
$status = 'apr';
}elseif($_POST['StatusTransacao'] == 'Em AnĂ¡lise'){
$status = 'anl';
}elseif($_POST['StatusTransacao'] == 'Aguardando Pagto'){
$status = 'wtg';
}elseif($_POST['StatusTransacao'] == 'Completo'){
$status = 'cmp';
//nothing more happens here - client must click on 'mark as shipped' before cart is removed and history data is loaded
}elseif($_POST['StatusTransacao'] == 'Cancelado'){
//reshelf - don't set $status, because the cart's about to be destroyed
$this->carrinho_model->reshelf(array($id));
}
if (isset($status)){
$this->carrinho_model->update_carrinho($id, array('status' => $status));
}
} else if ($result == "FALSO") {
$notice = "PagSeguro return was invalid.";
$this->log($notice);
$notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
$this->email_notice($notice);
} else {
$notice = "Error in PagSeguro request";
$this->log($notice);
$notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
$this->email_notice($notice);
}
}
SECURITY UPDATE:
After posting, I soon realized that I was opening myself up to hack attempts. The function necessarily has to be public, so anyone who knows the name of the function could access it and post 'simulate' to get immediate verification. Then they could pass whatever data they wanted.
I changed the name of the function to something that would be impossible to guess, and when not in production mode, I've disabled the simulate option.
The problem was that my CSRF protection causes a redirect when the proper CSRF code isn't sent with the POST. My simulator was working, because I copied the HTML generated by a dynamic simulator that I made on the site in question. I then pasted the HTML to create a static simulator and put it under a different URL. Along with the HTML, I inadvertently pasted the CSRF code as well. The static simulator worked fine until the code expired. I quit using it after a couple times, so I didn't discover that it was no longer working until today.
I know that this exact scenario probably won't happen again in the next 500 years, but things like CSRF security can cause problems with things like payment gateways if not disabled for the function receiving the POST.

json_encode adding too many double quotes

I am working on a PHP web service that returns data in JSON form. I am at a point where I am now testing the web service with a jQuery/javascript file. It seems to be making the calls and receiving data correctly but the return values from the server seem to have too many double quotes.
PHP:
public static function getToken($username, $password)
{
$token = AuthenticationController::authenticate($username, $password);
if ($token)
{
$user = AuthenticationController::getUserFromToken($token);
if (UserController::userIsVerified($user->id))
{
$t = array('token' => $token);
return json_encode($t);
}
return json_encode(array('error' => 'This account has not been verified. Check email and click the provided link to verify the account.'));
}
return json_encode(array('error' => 'Authentication failed.'));
}
JS:
req.done(function(msg)
{
if (msg.error)
{
error = true;
message = msg.error;
}
else if (msg.message)
{
message = msg.message;
}
else if (msg.token)
{
token = msg.token;
}
else
{
error = true;
message = "An unknown error has occured.";
}
});
For one, the msg object is not coming back as a JSON object but instead it comes in as a string, so I have to do a $.parseJSON(msg) on it. What you see below, the token variable ends up writing out to be "mylongtoken" (quotes included). And if you look at that variable in firebug, it is like this: ""mylongtoken"". Is this just default behavior and I need to strip the quotes out?
First, to enable jquery to parse your response as json, you must return an appropriate content type. application/json seems appropriate.
For added security, you can add X-Content-Type-Options: nosniff to prevent browsers that get tricked into reading your JSON as a normal page to try any content sniffing which might enable HTML parsing and XSS:
Second, If you get two sets of quotes, then something you coded does add them. json_encode() does not:
echo json_encode(array('token' => 'tokenstring'); will output {"token":"tokenstring"} - no surrounding quotes. Any quotes inside any strings will be escaped using a backslash.

500 Server Error When Using Foursquare API

I'm using php-foursquare library for Foursquare API calls.
This is my index.php
require_once("FoursquareAPI.class.php");
$client_key = "blabla";
$client_secret = "blabla";
$redirect_uri = "http://localhost/4kare/index.php";
// ($redirected_uri equals to registered callback url)
// Load the Foursquare API library
$foursquare = new FoursquareAPI($client_key,$client_secret);
// If the link has been clicked, and we have a supplied code, use it to request a token
if(array_key_exists("code",$_GET)){
// example $_GET['code'] = FJRW1Z5TZ3H0E3Y2WN4Q0UPSH1PEIDADTZDHYKVG32DJTH2E
$token = $foursquare->GetToken($_GET['code'],$redirect_uri);
}
// If we have not received a token, display the link for Foursquare webauth
if(!isset($token)){
echo "<a href='".$foursquare->AuthenticationLink($redirect_uri)."'>Connect to this app via Foursquare</a>";
// Otherwise display the token
}else{
echo "Your auth token: $token";
}
But GetToken() method returning 500 server error . THis is source code of GetToken () method :
public function GetToken($code,$redirect){
$params = array("client_id"=>$this->ClientID,
"client_secret"=>$this->ClientSecret,
"grant_type"=>"authorization_code",
"redirect_uri"=>$redirect,
"code"=>$code);
$result = $this->GET($this->TokenUrl,$params);
$json = json_decode($result);
$this->SetAccessToken($json->access_token);
return $json->access_token;
}
I'm not using php-foursquare, but I faced a similar problem when using Guzzle to connect to 4sq REST endpoints.
It turns out that a request will result in an unhandled exception if you don't wrap it in a try catch block and it gets anything different than a 200 header. I couldn't understand why I was getting error 500, but when I captured and printed the exception it showed Foursquare returning a 401 with a much more informative msg. In my case, the redirecting URL had a typo.
try {
$result = $this->GET($this->TokenUrl,$params);
} catch (Exception $e) {
echo $e->getMessage();
}
Well, here is the problem. You don't have any control over 4square's servers, so you don't have enough information to go about this without guessing. I would do two things:
Google the API call you are using and see if it's a common problem with a commmon answer
Email 4square - it's their server spitting out an error message with no useful information.

Categories