problem
i tried with $request->request->all() //var_dump output:array(0){}
symfony code
public function registerAction(Request $request) {
var_dump($request->request->all());die;
}
Angular2 service
export class UserRegistrationService {
constructor(private http: Http) { }
private headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
private insertdataUrl =
'http://localhost/abc/web/app_dev.php/api/v1/register-user';
/* create new user */
create(name: string): Promise<UserDetails> {
return this.http
.post(this.insertdataUrl, JSON.stringify({name: name}), {headers: this.headers})
.toPromise()
.then(res => res.json().data as UserDetails)
.catch(this.handleError);
}
FormData
{"name{"email":"abc#gmail.com","username":"abc","password":"","repeatpassword":""}}:
solution that works
$data = json_decode(file_get_contents('php://input'), true);
// able to get paramters //get,or //post
can anyone suggest why request doesn't print some values.
here im posting form from angular2.
Symfony uses different containers for Post and Get. Try this way.
# Post
$request->request->all()
# Get
$request->query->all()
solution that worked for me
i changed headers
from
private headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
To
private headers=new Headers({ 'Content-Type': 'application/json' });
now im able to recieve data.
Related
I'm using Angular with PHP and trying to post an object. Request status is 200, but $_POST array is empty. Data I'm sending is a valid JSON Object.
sendTweet(){
if(!this.username || !this.tweet){
alert("Enter username or tweet");
return;
}
const newTweet:Tweet = {
username: this.username,
tweet: this.tweet
}
//Call Service
this.testService.postTweet(newTweet).subscribe((response)=>{console.log(response)},
(err:any)=>{
console.log(err.message);
});
}
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
postTweet(tweet:Tweet):Observable<Tweet>{
const url = `${this.apiUrl}/?page=submit&action=add`;
return this.http.post<Tweet>(url,tweet, httpOptions);
}
PHP:
if (isset($_POST['tweet'])&&isset($_POST['username'])) {
//Sending tweet to the db
} else{
print_r($_POST);
}
i dont know if its a backend problem with php but in my project i have it a little bit diferent (i am using .net core for backend)
for example in my project:
//service component WebScrapLinkService
get(): Observable<Any[]> {
return this.http.get<Any[]>(this.url)
.pipe(map(res => res));
}
//main component
getRegisters() {
this.getProductsSub = this.crudService.get()
.subscribe(data => {
this.registers = data;
})
}
//variables
public registers: Array<object> = [];
//the service goes in the constructor
private crudService: WebScrapLinkService
this works fine for me, i hope it is useful for you
It was just me not knowing that in PHP you have to parse HTTP_RAW_POST_DATA in order to get the data.
I am posting data to Laravel and expect a success response, but it catches the exception TypeError: Network request failed. Using get methods and login post methods using Laravel passport works all fine.
Adding 'Content-Type': 'application/json' to headers creates Network request failed for the login methods.
Postman returns valid errors or success, so works totally as expected.
Debugging showed that the request has been sent to Laravel and routing is correct as Visual Studio Code debugger stops at a breakpoint at return response.
public function postMessages()
{
...
return response()->json(['success' => 'success'], 200);
}
Route::middleware('auth:api')->group(function () {
Route::post('messages', 'Api\ChatController#postMessages');
});
export const fetchApi = async (endPoint, method = 'get', body = {}) => {
const accessToken = authSelectors.get().tokens.access.value;
const accessType = authSelectors.get().tokens.access.type;
let headers = {
...(accessToken &&
{
Authorization: `${accessType} ${accessToken}`
}
)
};
let response;
if (method=='get' || Object.keys(body)==0 ) {
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers
});
} else {
var formData = new FormData();
Object.keys(body).forEach(type => {
formData.append(type, body[type]);
});
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers,
body: formData
});
console.log('fetch response: ' + JSON.stringify(response));
}
let responseJsonData = await response.json();
return responseJsonData;
}
export const postMessages = (eidug, type, name, messages) => fetchApi('/message', 'post', {
'eidug': eidug,
'type': type,
'name': name,
'messages': messages
});
I expect a response without any exception like Postman. What can be going wrong?
Have you enabled CORS in the backend? Once open inspect->network and then run fetch. Show if there are any errors.
Am using Angular2 as front end and php as my server script . I want to pass the user login details to server with the http.get() .
I used like..
var uname = event.email;
var pass = event.password;
this.http
.get('http://192.168.0.100:80/php/logincheck.php?user='+uname+'&pwd='+pass).subscribe();
but it can't get the 2 values. I can simply pass a single value easily.
If 2 values can be passed like this. Please help ..
I do not think it is secured to send a password without doing some sort of encrypting. but if you want to send some data to your server request it is possible to send them in the request headers as well. see below code snippet.
//on import section
import { Http, Headers, RequestOptions } from '#angular/http';
//inside your login function
let requestUrl= "http://192.168.0.100:80/php/logincheck.php"
let requestOptions = new RequestOptions();
requestOptions.headers = new Headers({ 'Content-Type': 'application/json', 'email': event.email,
'pwd': event.password });
this.http.get(requestUrl, this.requestOptions).subscribe();
Try like this :
import { URLSearchParams, BaseRequestOptions } from '#angular/http';
getLogin() {
const options: BaseRequestOptions = new BaseRequestOptions();
const params: URLSearchParams = new URLSearchParams();
params.set('uname', event.email);
params.set('pass', event.password);
options.search = params;
return this.http.get('http://192.168.0.100:80/php/logincheck.php', options)
.map(res => res.json())
}
Server side :
<?php
echo $_GET['uname'];
?>
or
$url = parse_url($url);
parse_str($url['query'], $queryParams);
echo $queryParams['uname'];
echo $queryParams['pass'];
i have set up the normal CSRF stuff etc and would work well, but then when i go and use ajax using the whatwg-fetch api (https://github.com/github/fetch)
Now all seem ok and all works well to what i have. BUT! Then I add the CSRF settings as below and it fails, all the time:
So, I have used the normal, but it fails and in the header I get the message: Failed CSRF check!
$app->add(new \Slim\Csrf\Guard);
But I wanted to add own message etc so have added the following, but still it does not pass.
$container['csrf'] = function ($c) {
$guard = new \Slim\Csrf\Guard;
$guard->setFailureCallable(function ($request, $response, $next) {
$request = $request->withAttribute("csrf_status", false);
return $next($request, $response);
});
return $guard;
};
$app->add($container->get('csrf'));
Then in my class i check it with:
if (false === $req->getAttribute('csrf_status')) {...}else{//all ok}
But what ever happens it always fails.
in my js i am adding the token details to the request like:
fetch('/post/url',{
method: 'POST',
headers: {
'X-CSRF-Token': {
'csrf_name':csrf_name,
'csrf_value':csrf_value
}
},
body: new FormData(theForm)
i have looked in the posted data etc and the form data is submitted including the csrf values etc. SO the require csrf data is being sent via the form as well as the header?
So how can I get the ajax functionality to work with the Slim CSRF, what am I missing?
Thanks in advance
I was also unable to get fetch to put the tokens into the body. I decided to extend the class so I could modify the __invoke method. I have added some code to pull the csrf from the headers.
in your dependencies now use this class.
$c['csrf'] = function ($c) {
return new \Foo\CSRF\Guard;
};
The extended class.
<?php
namespace MYOWN\CSRF;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* CSRF protection middleware.
*/
class Guard extends \Slim\Csrf\Guard
{
public function __construct(
$prefix = 'csrf',
&$storage = null,
callable $failureCallable = null,
$storageLimit = 200,
$strength = 16,
$persistentTokenMode = false
) {
parent::__construct(
$prefix,
$storage,
$failureCallable,
$storageLimit,
$strength,
$persistentTokenMode);
}
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
$this->validateStorage();
// Validate POST, PUT, DELETE, PATCH requests
if (in_array($request->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) {
$body = $request->getParsedBody();
$body = $body ? (array)$body : [];
$name = isset($body[$this->prefix . '_name']) ? $body[$this->prefix . '_name'] : false;
$value = isset($body[$this->prefix . '_value']) ? $body[$this->prefix . '_value'] : false;
if (!empty($csrfTokens = $request->getHeader('x-csrf-token'))) {
$csrfTokens = json_decode($csrfTokens[0], true);
$name = isset($csrfTokens[$this->prefix . '_name']) ? $csrfTokens[$this->prefix . '_name'] : false;
$value = isset($csrfTokens[$this->prefix . '_value']) ? $csrfTokens[$this->prefix . '_value'] : false;
}
if (!$name || !$value || !$this->validateToken($name, $value)) {
// Need to regenerate a new token, as the validateToken removed the current one.
$request = $this->generateNewToken($request);
$failureCallable = $this->getFailureCallable();
return $failureCallable($request, $response, $next);
}
}
// Generate new CSRF token if persistentTokenMode is false, or if a valid keyPair has not yet been stored
if (!$this->persistentTokenMode || !$this->loadLastKeyPair()) {
$request = $this->generateNewToken($request);
}
// Enforce the storage limit
$this->enforceStorageLimit();
return $next($request, $response);
}
}
well after several attempts over the last day and narrowing it down to the fetch api was using I decided to go back to the trusted jQuery aJax methods, and this seems to have worked.
Seems the following body and the new FormData() was not being picked up:
fetch('/post/url',{
method: 'POST',
body: new FormData(theForm)
So switched it out for
$.ajax({
url : '/url/to/post',
type: "POST",
data: {key:value, kay:value}
And all worked well.
The next issue to look into then is the keys being refreshed on first ajax call, preventing anymore calls unless page is refreshed, but thats for another day
I had another go at this after reading one of the blogs from one of the creators. So you can ignore my previous answer.
Sending the csrf in the body with these headers passes the csrf check.
const data = {
'csrf_name': csrf_name,
'csrf_value': csrf_value,
};
fetch(apiUrl, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json, application/x-www-form-urlencoded; charset=utf-8',
},
}).then((response) => {
if (response.ok) {
return response.json();
}
return null;
}).then((json) => {
console.log(json);
}).catch(() => {
});
What finally helped me succeed with Slim PHP and the CSRF values while using fetch was adding credentials: 'include' to the fetch request, like:
const body = JSON.stringify({
csrf_name: csrfName.value,
csrf_value: csrfValue.value
// You can add more data here
});
fetch('/some/request', {
method: 'POST',
body: body,
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
}).then(...)
I am using laravel as backend and angujarjs as frontend to make an application. The frontend is sitting in another server, and therefore I have to deal with cross domain policy. I have enabled CORS, so I can "send" post request.
The problem is that when I am trying to get Input::all() in laravel, the request gets cancelled. (status shown 'cancelled' in Chrome network). But when I dont use Input, everything is OK.
//laravel
class SessionController extends BaseController {
protected $entity;
public function __construct(SessionEntity $entity)
{
$this->entity = $entity;
}
public function getLogin()
{
return Response::json('hello')->header('Access-Control-Allow-Origin', '*');
}
public function postLogin()
{
//$data = Input::all();
//return Response::json($data);
// $user = $entity->login($data);
// if($user)
// {
// return Response::json($user);
// } else {
// return Response::json($entity->errors(), 400);
// }
//the code below is OK (able to send response back) , but the code above is not, because I am using Input::all()
$data = array(
"email" => "324234",
"password" => "654321"
);
return Response::json($data);
}
}
//angularjs
.controller('LoginController', ['$scope', '$http', function($scope, $http) {
$scope.send = function(credential) {
$http({
method: 'POST',
url: 'http://localhost:8000/api/session/login',
data: credential,
headers: {
'Content-Type': 'application/json; charset=UTF-8'
}
})
.success(function(data, status, headers) {
console.log(data);
console.log(status);
console.log(headers);
});
};
}]);
Here's the headers to enable CORS
App::after(function($request, $response)
{
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->headers->set('Access-Control-Max-Age', '1728000');
$response->headers->set('Content-Type', 'application/json; charset=UTF-8');
return $response;
});
What did I miss??
I found it. I use namespace but didn't include 'use Input'.
silly me...
Also, I found that I have to explicitly set Content-Type to 'application/json' in order to receive data using Input::all() in laravel, otherwise I get no data.
For cross domain requests you must use jsonp instead json