Send Data from Angular Application to API through HTTP POST - php

I am trying to send a single object from my angular 5 apllication to an php API in JSON format With HTTP POST, but i cant get it to work. I know this might be very basic but I am new to this topic and google cant help me or i am not searching the right keywords.
Errors:
1: With httpOptions parameter in data.service.ts -> http post method
2: Without httpOptions parameter in data.service.ts -> http post method
Line 55 in the php file is this one: $name=$_POST["name"]; I've also marked it in the file.
3: Network
I do not understand why i get the "405 not allowed Method Error" when i add a the Content-Type Header: application/json (Error 1). If i remove it the error wont show up but no data arrives at the API (Error 2).
The Content Type Header is set in the php file of the API. POST Method along other is also allowed in the php file.
I tested the API with the Restlet Client. it worked with Content-Type: application/x-www-form-urlencoded but also not with application/json:
json
x-www-form-urlencoded
What am I doing wrong?
Angular v5 -> package.json
Angularapp -> localhost:4200
API -> localhost:81 Apache
data.service.ts -> full File
const httpOptions = { headers: new HttpHeaders({ 'Content-Type':'application/json' })};
...
saveName(name: Name) {
const body = JSON.stringify(name.name);
return this.http.post('http://localhost:81/apitest/src/app/data/name.php', body, httpOptions);
}
API
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTION");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$connection = mysqli_connect('localhost', 'api', 'test', 'apitest');
$request_method = $_SERVER['REQUEST_METHOD'];
switch($request_method){
case 'GET':
if(!empty($_GET['nameId'])){
$nameId = intval($_GET['nameId']);
getNames($nameId);
} else {
getNames();
}
break;
case 'POST':
insertNames();
break;
case 'PUT':
updateNames();
break;
case 'DELETE':
deleteNames();
break;
default:
header('HTTP/1.0 405 Method Not Allowed');
break;
}
function insertNames()
{
global $connection;
$name=$_POST["name"]; // LINE 55 | Undefined index: name in [...] on line <b>55</b><br />
if(isset($_POST['name'])){
$query="INSERT INTO form SET name='{$name}'";
if(mysqli_query($connection, $query))
{
$response=array(
'status' => 201,
'status_message' =>'Name Added Successfully.'
);
}else
{
$response=array(
'status' => 400,
'status_message' =>'Name Addition Failed.'
);
}
}
else
{
$response=array(
'status' => 400,
'status_message' =>'Request Body Empty.'
);
}
header('Content-Type: application/json');
echo json_encode($response);
app.component.ts -> full File
saveName() {
this.dataService.saveName(this.name).subscribe(
data => {
this.getNames();
return true;
}, error => {
console.error('Failed');
}
);
}
HTML Form
<html>
<head>
<title>API TEST</title>
</head>
<body>
<form action="data/name.php" method="POST">
<label for="name">Name: </label>
<input type="text" name="name" [(ngModel)]="name.name">
{{name.name}}
<button name="post" (click)="saveName()">post</button>
</form>
</body>
</html>

did you try this?
$json = file_get_contents('php://input');
$obj = json_decode($json, true);
$name = $obj['name']
from: Reading JSON POST using PHP

try to modify this, you missed S for OPTIONS method, and add HEAD method:
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, HEAD, OPTIONS");
When you invoke the CORS requests, the browser sends the OPTIONS request to the server to know what methods are allowed. This is so-called: Preflighted request

Related

Ionic Angular HTTP POST request to PHP

I'm trying to do a basic POST request from my ionic angular app using the HttpClient from Angular. From that POST, I need to pass the payload to PHP file for me to manipulate another function in the PHP.
I can seem to echo the whole data, but trying to get the single value gives an error.
Below is my code under home.ts
test() {
let data = {
firstname: "John",
lastname: "Wick"
}
const headers = new HttpHeaders();
headers.set('Content-Type', 'application/json; charset=UTF-8');
headers.set('Access-Control-Allow-Origin', '*');
headers.set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
this.http.post(this.php_url, data, {headers: headers}).subscribe((res) => {
console.log("Posted successfully")
console.log(res);
}, (err) => {
console.log(err.error);
});
}
In my index.php file, I have the code below.
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Content-Type: application/json');
$json = file_get_contents('php://input');
echo $json->firstname;
?>
I am able to echo $json, but not when trying to get the single value. How do I get the single value from the JSON data?
you have to use
print_r($json['firstname']);
insted of
echo $json->firstname;

CORS headers not working for File Upload from Angular to PHP

I am trying to upload images from my Angular 8+ frontend to my php backend and sending text data works without a problem, but wanting to send image files to a folder in my wamp directory, no cigar unfortunately...
It worked earlier, but this morning it decided it did not want to work anymore. I tried adding to the CORS headers, but nothing seems wrong there.
html:
<input type="button" value="Test" (click)='Advertise($event.target.files)'>
component:
ToUpload()
{
let images = this.carImages.nativeElement;
let j=10;
for(let i of images.files)
{
console.log(i);
if(i.type=='image/jpeg')
{
let frmData = new FormData();
frmData.append('file',i,(j+'.jpg').toString());
this.uploadService.UploadImages(frmData).subscribe(val=>
{
})
}
if(i.type=='image/png')
{
let frmData = new FormData();
frmData.append('file',i,(j+'.png').toString());
this.uploadService.UploadImages(frmData).subscribe(val=>
{
})
}
j++;
}
}
Advertise(files:FileList)
{
this.ToUpload();
}
service:
UploadImages(image:FormData):Observable<any>
{
return this.httpClient.post(this.apiURL+"/api/BLL/imageUpload.php?action=upload",image) as Observable<any>;
}
CORS_Headers.php
<?php
// Default Header
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization,Content-Range, Content-Disposition, Content-Description');
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Credentials: true");
header("MIME-Version: 1.0");
header("Content-type:text/html;charset=UTF-8");
// Response type header
header('Content-Type: application/json');
?>
imageUpload.php
<?php
require_once '../BLL/CORS_Headers.php';
//require '../DAL/DBHandler.php';
//use DAL\DBHandler;
$action=$_GET['action'];
if($action=='upload')
{
$tempPath = $_FILES['file']['tmp_name'];
// Get File Name
$actualName = $_FILES['file']['name'];
// New path
$actualPath = '../Images/' . $actualName;
//$tempPath = compressImage($tempPath,$actualPath,60);
// Move File into new path
move_uploaded_file($tempPath, $actualPath)
// Get real path of moved file here
$realPath = realpath(__DIR__ . '/' . $actualPath);
// Delete the file
echo "Uploaded";
}
Expected result: Just do the upload
Actual result: Access to XMLHttpRequest at 'http://localhost:3000/api/BLL/imageUpload.php?action=upload' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://localhost:3000/api/BLL/imageUpload.php?action=upload", ok: false, …}
try this
Add below Code in .htaccess file PHP(Server) side
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "X-Requested-With, content-type"
</IfModule>
Angular Code
page.html
<input type="file" (change)="fileUpload($event)" />
npm install
"rxjs": "~6.5.1", //npm i rxjs#6.5.1 --save
"rxjs-compat": "^6.5.2" // npm i rxjs-compat#6.5.2 --save
page.ts
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/concatMap';
fileUpload(event){
let formData = new FormData();
formData.append('file', event.target.files[0]);
this.ImageUpload(formData).subscribe(val => {
//enter custom code
})
}
ImageUpload(formData):Observable<any>{
var token = localStorage.getItem('keyToken');
const myHeaders = new HttpHeaders({ 'Authorization': token });
return this.http
.post(URL, formData,{headers:myHeaders})
.concatMap(data=>{
return Observable.of(data);
})
}

PHP api sends HTTP_response_code(400) no matter what

i wrote a Simple PHP crud api and i'm getting HTTP_response_code(400) no matter what i do.
in the api a file named create.php is responsible for inserting new items in the database it checks if the data it receives from ajax isn't empty and then proceeds to creation if it's empty it sends an HTTP_response_code(400).
but, no matter what i do it always sends the HTTP_response_code(400) even though the data is not empty.
i thought the problem was coming from ajax first but after debugging i found out that ajax in facts gets the proper data from the form and sends it.
here is my create.php file
$db = $database->getConnection();
$consumable = new consumable($db);
//get json
$json = file_get_contents("php://input");
// get posted data
$data = json_decode($json);
// make sure data is not empty
if(
!empty($data->reference) &&
!empty($data->price) &&
!empty($data->description) &&
!empty($data->category_id) &&
!empty($data->quantity)
){
// set consumable property values
$consumable->reference = $data->reference;
$consumable->price = $data->price;
$consumable->description = $data->description;
$consumable->category_id = $data->category_id;
$consumable->quantity = $data->quantity;
$consumable->created = date('Y-m-d H:i:s');
// create the consumable
if($consumable->create()){
// set response code - 201 created
http_response_code(201);
// tell the user
echo json_encode(array("message" => "consumable was created."));
}
// if unable to create the consumable, tell the user
else{
// set response code - 503 service unavailable
http_response_code(503);
// tell the user
echo json_encode(array("message" => "Unable to create consumable."));
}
}
else{
// tell the user data is incomplete
// set response code - 400 bad request
//http_response_code(400);
// tell the user
echo json_encode(array("message" => "Unable to create consumable. Data is incomplete."));
echo json_encode($json);
}
and here is my ajax:
$(document).on('submit', '#create-consumable-form', function(){
alert("submit");
// get form data
var form=$(this).serializeObject();
var form_data=JSON.stringify(form);
console.log('a',form);
console.log(form_data);
// submit form data to api
$.ajax({
url: "http://localhost:3000/consumable/create.php",
type : "POST",
contentType : 'application/json',
data : form_data,
success : function(result) {
// consumable was created, go back to consumables list
showconsumables();
},
error: function(xhr, resp, text) {
// show error to console
console.log(xhr, resp, text);
}
});
return false;
});
after filling out the form and submitting instead of adding the entry to the database and sending a 201 OK it shows me the following error:
jquery.js:2 OPTIONS http://localhost:3000/consumable/create.php 400 (Bad Request)
send # jquery.js:2
ajax # jquery.js:2
(anonymous) # create-consumables.js:87
dispatch # jquery.js:2
v.handle # jquery.js:2
index.html:1 Access to XMLHttpRequest at 'http://localhost:3000/consumable/create.php' from origin 'http://localhost:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
and this is the result of my console.log
a {reference: "BT3000", price: "10", quantity: "5", description: "description", category_id: "3"}
create-consumables.js:85 {"reference":"BT3000","price":"10","quantity":"5","description":"description","category_id":"3"}
the weird thing is when i comment the HTTP_response_code(400) line in my create.php file it works perfectly does anyone have any idea of the cause of this behaviour?
Try to put header() in your create.php file:
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
json_decode returns null if it cannot decode it. It seems it does just that. Maybe you need to url_decode and/or stripslashes the contents before you can decode it. As Ahmed is saying, try to output the $data variable and the output of the json_decode and file_get_contents("php://input"); and you will see the mistake soon enough.
Also be aware that !empty(0) and !empty(false) returns true. So if your variable has a value which is 0 or false then it will return 400 in this case as well. This is not the issue in your example, but might become an issue later.
the problem was caused by the fact that the content-type in my headers was application/json and i was using postman for testing and i had left it to default content-type which is text

input->post and $_POST are empty in CodeIgniter API calling from Angular 4, what is the right way to make a post request in angular 4

This is the first time I'm making a post method request from Angular to CodeIgniter rest API.
postUsertask(Userid,TaskName)
{
let body ={
userid:Userid, taskname:TaskName
};
console.log(body);
return this.http.post("http://localhost/ci-abc/api/add_task",JSON.stringify(body) )
.map(res => res.json());
}
API method in codeigniter:
function add_task_post()
{
$obj=json_decode(file_get_contents('php://input'));
$taskname = $obj->taskname;
$userid = $obj->userid;
if (!$taskname || !$userid) {
$this->response("Enter taskname and userid to add", 400);
} else
$result = $this->todo_model->add_task($taskname, $userid);
if ($result === 0) {
$this->response("Task could not be added. Try again.", 404);
} else {
$this->response("success", 200);
}
}
Had to include to access the data
$obj=json_decode(file_get_contents('php://input'));
Because the $this->input->post and $_POST were empty and the data recieved from angular was an object so had to be accessed with -> notation. I am curious that this is not the right and ethical way to do this. Also when I didn't put JSON.stringify it gave me Cross Origin Request blocked error so that's why I put it. How should I make POST and PUT request in angular4 to rest API in CodeIgniter?
How do I get rid of CORS error which doesn't let me call the API method, if I can get rid of CORS error then I could also remove JSON.stringify which will send the data as it is and I believe the data should be accessed via input->post or $_POST.
EDIT 2:
These sort of errors while making POST PUT and DELETE API call.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost/ci-abc/api/del_task?taskid=34.
(Reason: CORS preflight channel did not succeed)
EDIT (Perfect Solution):
Found out that the formdata object approach was deprecated so I just included a header in options and included in the API call http.post method which works fine and is much better solution.
constructor(public http:Http) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let options = new RequestOptions({ headers: headers });}
createUser(userName)
{
let body = { username:userName};
return this.http.post("http://localhost/ci-abc/api/create_user",body,this.options)
.map(res => res.json());
}
Deprecated approach (Works but deprecated/not usual practice):
Took few hours but found the solution, I created body as a new formdata object, appended parameters to it as key and their values and it worked fine now I am retrieving through $this->input->post.
let body = new FormData;
body.append('userid', Userid);
body.append('taskname', TaskName);
console.log(body);
return this.http.post("http://localhost/ci-abc/api/add_task",body)
.map(res => res.json());
Using these headers in the constructor of my codeigniters API controller
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Access-Control-Allow-Origin');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
API method:
function add_task_post()
{
$userid = $this->input->post('userid');
$taskname = $this->input->post('taskname');
if (!$taskname || !$userid) {
$this->response("Enter taskname and userid to add", 400);
} else
$result = $this->todo_model->add_task($taskname, $userid);
if ($result === 0) {
$this->response("Task could not be added. Try again.", 404);
} else {
$this->response("success", 200);
}
}

Cross-Domain jQuery.Ajax request - Chrome extension

I would like to realize an Google Chrome extension, which would show a notification following the result of an Ajax request.
I coded the function which allows to create a notification, so I just have to do the Ajax request which fetches a .php file on a remote server which belongs to me. This request just failed, nothing happened. Nevertheless when I try to realize the request since my server towards my server (without the extension), no problem, I deducted from it that it was a problem of "Cross-Domain"...
Here are the important elements (for the problem) of the manifest.json (I just put all possible permissions^^) :
{
"background": {
"scripts": ["myScript.js", "jquery-2.1.4.min.js"]
},
"manifest_version": 2,
"permissions": [ "http://*/", "https://*/" , "http://*/*" , "https://*/*", "tabs", "notifications", "browsingData", "webRequest", "webNavigation" ],
...
...
}
Here is the AJax request in myScript.js :
(The spawnNotification function works perfectly, tested without the request)
$.ajax({
url: "http://www.domain.com/test/get.php",
type: "GET",
crossDomain : true,
success: function() {
spawnNotification("Title", "work", "img/notif.png", "http://www.domain.cor/forum/");
},
error: function() {
spawnNotification("Title", "error", "img/notif.png", "http://www.domain.co/forum/");
}
});
And finally, the get.php file :
<?php
header("Content-Type: text/plain");
header("Access-Control-Allow-Origin: *");
$str = 15;
echo $str;
?>
What am I doing wrong here? Thanks !
 
( Here are some topics that did not help me...
Chrome extension Cross Domain Request
Chrome extension xhr cross domain request gives error:"is not allowed by Access-Control-Allow-Origin." )
You need to provide more response headers than just that one, see the Cross-Origin Resource Sharing specification for details.
Here's pseudo-code (from my other answer here) of what's required in your server code (sorry, don't write much PHP, hence pseudo-code):
// Find out what the request is asking for
corsOrigin = get_request_header("Origin")
corsMethod = get_request_header("Access-Control-Request-Method")
corsHeaders = get_request_header("Access-Control-Request-Headers")
if corsOrigin is null or "null" {
// Requests from a `file://` path seem to come through without an
// origin or with "null" (literally) as the origin.
// In my case, for testing, I wanted to allow those and so I output
// "*", but you may want to go another way.
corsOrigin = "*"
}
// Decide whether to accept that request with those headers
// If so:
// Respond with headers saying what's allowed (here we're just echoing what they
// asked for, except we may be using "*" [all] instead of the actual origin for
// the "Access-Control-Allow-Origin" one)
set_response_header("Access-Control-Allow-Origin", corsOrigin)
set_response_header("Access-Control-Allow-Methods", corsMethod)
set_response_header("Access-Control-Allow-Headers", corsHeaders)
if the HTTP request method is "OPTIONS" {
// Done, no body in response to OPTIONS
stop
}
// Process the GET or POST here; output the body of the response
#T.J. Crowder
Thanks Crowder, I tried to write it in PHP and I first tried that for my get.php :
<?php
header("Content-Type: text/plain");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
$str = 15;
echo $str;
?>
It doesn't work so I searched a bit with what you said, and found that https://stackoverflow.com/a/9866124/5733765
get.php :
<?php
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
}
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
$str = 15;
echo $str;
?>
But still doesn't work
I found the problem... we have to use xhr
myScript.js :
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://domain.com/test/get.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
alert(xhr.responseText);
}
}
xhr.send();
Thanks for your help ;)
EDIT: the real problem was to define jquery.js after in the myScript.js
manifest.json:
"background": {
"scripts": ["jquery-2.1.4.min.js", "notification.js"]
},

Categories