Develop a simple backbone and php application but on a server i get 403 error
whenever i use a put method
Of course when using more traditional method such as get and post i do not get any problem.
Could any one advise on what is the specific settings to tune because on another server it work great.
My suspects are
apache configuration
php configuration
Thanks in advance.
Code Sample
PHP file
$this -> method = $GLOBALS['_SERVER']['REQUEST_METHOD'] ;
switch ( $this -> method ) {
case ( 'POST' ) :
foreach ( $_POST as $k => $v )
$data -> $k = $v ;
$data = $this -> save ($data) ;
$this -> output( $data ) ;
break
case ( 'PUT' ) :
$putdata = fopen("php://input", "r");
while ($d = fread($putdata, 1024))
$data .= $d ;
$data = json_decode( $data ) ;
$data = $this -> save ($data) ;
$this -> output( $data ) ;
break ;
case ( 'DELETE' ) :
$data = $this -> delete($data) ;
$this -> output( $data ) ;
break ;
case ('GET') :
default:
$data = $this -> retrieve () ;
$this -> output( $data ) ;
break ;
}
Note that backbone does not need form using jquery ajax to make an xhr request
arguments: {
0: {
contentType: "application/json"
data: {
"id":0,
"dat":"10-03-2014",
"title":"Bunk bed",
"current":false,
"enrole":[],
"result":"",
"starts":{"m":{},"f":{}},"sex":"m"}
}
dataType: "json"
emulateHTTP: false
emulateJSON: false
error: function (resp) { ... }
parse: true
processData: false
success: function (resp) { ... }
type: "PUT"
url: "event" // event is a folder with index.php
validate: true
}
}
Backbone.$.ajax.apply(Backbone.$, arguments);
Here is the request made by the browser
Request Method:PUT
Status Code:301 Moved Permanently
Request Headersview parsed
PUT /maa/event HTTP/1.1
Host: localhost
Connection: keep-alive
Content-Length: 123
Cache-Control: no-cache
Pragma: no-cache
Origin: http://localhost
X-Requested-With: XMLHttpRequest
Content-Type: application/json
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
Referer: http://localhost/maa/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,fr;q=0.6,fr-FR;q=0.4
Request Payloadview parsed
{"id":0,"dat":"10-03-2014","title":"Acton Vale","current":false,"enrole":[],"result":"","starts":{"m":{},"f":{}},"sex":"m"}
Everything work except for the put which generates a 301 error
Related
This question already has answers here:
Receive JSON POST with PHP
(12 answers)
Closed 1 year ago.
I am using jQuery to submit the following request:
$.ajax({
url: encodeURI('/server/api/user/update.php/'),
method: 'POST',
contentType: 'application/json',
headers: {
'Authorization': 'Bearer ' + utility.getJsonWebToken()
},
data: JSON.stringify(e.model),
dataType: 'json'
})
And I have the following PHP code that verifies that the request is valid and contains the necessary body:
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a POST request.';
echo json_encode($returnedJson);
return;
}
// check for bad request
$errors = array();
$user = new UserModel();
foreach (UserModel::$RequiredColumnNames as $property) {
$success = ControllerUtility::isValueInRequest($_POST, $property);
if (!$success) {
array_push($errors, $property);
continue;
}
$user->$property = $_POST[$property];
}
if (count($errors) > 0) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following properties are missing from the request: ' . join(', ', $errors);
echo json_encode($returnedJson);
return;
}
Every time I submit the request, I get 400 error with the 'Malformed request syntax. The following properties are missing from the request: ...' error message.
I echoed the $_POST and $_REQUEST but in both instances and empty array is returned.
I verified that the request headers is a POST:
POST /server/api/user/update.php/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Authorization: Bearer -removed-
X-Requested-With: XMLHttpRequest
Content-Length: 180
Origin: http://localhost
Connection: keep-alive
Referer: -removed-
Sec-GPC: 1
And the fields are included in my request JSON:
{
"CreatedBy": null,
"CreatedOn": "2021-02-28 13:53:54",
"DeletedOn": null,
"Email": "-removed-",
"ModifiedBy": "1",
"ModifiedOn": "2021-02-28 16:35:51",
"UserId": "1",
"Username": "Adminn"
}
I have even removed the content-type header from my PHP without success. I've also tried just passing e.model instead of calling stringify in the AJAX request. At this point I'm at a loss as to what I'm doing wrong.
// echo the json string from php://input.
file_get_contents('php://input');
I want to post data from Frontend to MYSQL database in the backend using Laravel API. I tried the following code, but it outputs a 500: Internal Server Error while trying to post.
public function postOrder(Request $request)
{
/*
$request is a JSON Object which looks like
{"order":{"table_id":2,"food_id":4,"status":1}}
*/
$order = new Order();
$order->table_id = $request->order->table_id;
$order->food_id = $request->food_id;
$order->user_id = $request->user_id;
$order->status = $request->status;
$order->save();
return response()->json(['message' => 'Order Added'], 201);
}
Should I json_decode($request)? How?
When I error_log($request), here's what I get:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Connection: keep-alive
Content-Length: 60
Content-Type: application/json
Host: localhost:8000
Origin: http://localhost:8100
Referer: http://localhost:8100/
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML
, like Gecko) Chrome/55.0.2883.87 Safari/537.36
X-Xsrf-Token: eyJpdiI6IlJpNVV1ejhZTDVaSnVcL09lVkFIZER3PT0iLCJ2YWx1ZSI6IjNFK0
NnSXFsczd1eGJBRjZiZFc3U3lBUE9jR1lNZ0hSN0ZWNVpyWHlyWGE1TVZvZW9vK1F0eExXVjdkQzdPS
nBISEM3UXBINGQxZ09jTCttQ0huYmlnPT0iLCJtYWMiOiJmZWNiMTY1NTJjNjYyNDZjM2Q3YTE2N2Jl
NWNmYjgwYmNiMTlkNThjYWQ2NjEyYjk3YzQ4ZTVkYjQwMzFjY2VlIn0=
{"order":{"table_id":2,"food_id":4,"time":"333","status":1}}
You need to use json_decode() to get an associative array:
$json = '{"order":{"table_id":2,"food_id":4,"time":"333","status":1}}';
$array = json_decode($json, true);
var_dump($array['order']); //Here you can see that it is an associative array with the needed values now
Then you can create a model based on it.
$order = Order::create($array['order']);
that could be the solution:
json_decode($request, true)['order']['table_id']
When I try to implement auto-complete using the code below :
$('#keyword').autocomplete({
source : '/Dev/pages/search.php',
minLength : 3,
type : 'POST',
select: function( event, ui )
{
$(this).data("autocomplete").menu.element.addClass("yellow");
}
})
.data( "ui-autocomplete" )._renderItem = function( ul, item )
{
console.log(item);
return $( "<li>" )
.append( "<a>" + add3Dots(item.name,20) + "</a>" )
.appendTo( ul );
};
if (isset($_POST["term"])){
$term = trim($_GET['term']);
$parts = explode(' ', $term);
$p = count($parts);
$a_json = array();
$a_json_row = array();
$search = connexion::bdd_test();
$requete = "SELECT name from BDD_TEST.companies";
for($i = 0; $i < $p; $i++) {
$requete .= ' WHERE name LIKE ' . "'%" . $conn->real_escape_string($parts[$i]) . "%'";
}
$result = $search->query($requete);
while($donnees = $result->fetch(PDO::FETCH_ASSOC)) {
$a_json_row["name"] = $data['name'];
array_push($a_json, $a_json_row);
}
}
else
{
$a_json['call']=false;
$a_json['message']="Problem to collect word.";
}
$json = json_encode($a_json);
print_r($json);
When I test, if condition is not satisfied and I get the message directly from else " Problem to collect word . "
It means that $_POST["term"] is not defined.
How can I retrieve the input value ?
To be sure that values have been send, you can see what headers the browser sent to the web server with PHP for testing purposes.
This is possible using the apache_request_headers() function but it only works if PHP is run on Apache as a module.
How using apache_request_headers() :
If PHP is run on Apache as a module then the headers the browser send can be retrieved using the apache_request_headers() function. The following example code uses print_r to output the value from this function call:
print_r(apache_request_headers());
The output from the above using an example request from Google Chrome would output something similar to the following:
Array
(
[Host] => www.testing.local
[Connection] => keep-alive
[User-Agent] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.206.1 Safari/532.0
[Cache-Control] => max-age=0
[Accept] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[Accept-Encoding] => gzip,deflate,sdch
[Accept-Language] => en-US,en;q=0.8
[Accept-Charset] => ISO-8859-1,utf-8;q=0.7,*;q=0.3
)
Alternative when PHP is run as a CGI :
If PHP is not being run as a module on Apache, the browser headers should be stored in the $SERVER array with the key being the request header name converted to upper case, hypens replaced with underscores, and prefixed with HTTP
The same request above showing the relevent lines from $_SERVER are as follows:
[HTTP_HOST] => www.testing.local
[HTTP_CONNECTION] => keep-alive
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.206.1 Safari/532.0
[HTTP_CACHE_CONTROL] => max-age=0
[HTTP_ACCEPT] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate,sdch
[HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.8
[HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.3
The alternative method is create our own function if the apache_request_headers() function does not exist, which extracts just the values from $_SERVER and converts the key names to the same style as apache_request_headers(). This works like so:
if(!function_exists('apache_request_headers')) {
function apache_request_headers() {
$headers = array();
foreach($_SERVER as $key => $value) {
if(substr($key, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))))] = $value;
}
}
return $headers;
}
}
The new function is only declare if the function with that name does not already exist. The end result is that whether or not the internal PHP function exists, you will be able to call a function with this name in your code.
A loop is done though the $SERVER array and any whose key starts with HTTP is added to the array, and the key is translated via a series of function calls to be in the same format as returned by apache_request_headers().
View HTTP headers in Google Chrome
Chrome has a tab "Network" with several items and when I click on them I can see the headers on the right in a tab.
Press F12 on windows or ⌥⌘I on a mac to bring up the Chrome developer tools.
Try to retrieve value(s) without knowing HTTP methods
You can detect which request type was used (GET, POST, PUT or DELETE) in PHP by using
$_SERVER['REQUEST_METHOD']
For more details please see the documentation for the $_SERVER variable.
Or you can retrieve value(s) using $_REQUEST['you_variable'].
Note $_REQUEST is a different variable than $_GET and $_POST, it is treated as such in PHP -- modifying $_GET or $_POST elements at runtime will not affect the elements in $_REQUEST, nor vice versa.
I'm trying to read $_FILES uploaded by my AJAX upload form. This is the POST request:
POST myhost.net/csv.php
Host: myhost.net
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: application%2Fjson%2C%20text%2Fjavascript%2C%20*%2F*%3B%20q%3D0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
X-File-Name: Europe_1351.csv
Content-Type: multipart/form-data; charset=UTF-8
Pragma: no-cache
Cache-Control: no-cache
Referer: http://myhost.net
Content-Length: 26
Cookie: PHPSESSID=kourjvs7rm980d2cg4qvaav965
Connection: keep-alive
And on the server side, I got:
var_dump( $_FILES );
Even though 'multipart/form-data' is set, there aren't any data in $_FILES variable. Does this have something to do with PHP configuration? Thanks!
EDIT:
Here is my code:
<script src="//raw.githubusercontent.com/LPology/Simple-Ajax-Uploader/master/SimpleAjaxUploader.js">
$(document).ready(function()
{
var sizeBox = document.getElementById('sizeBox');
var uploader = new ss.SimpleUpload({
button: 'uploadButton', // file upload button
url: 'csv.php', // server side handler
name: 'uploadfile', // upload parameter name
contentType: 'multipart/form-data',
responseType: 'json',
allowedExtensions: ['csv'],
maxSize: 10 * 1024, // kilobytes
hoverClass: 'ui-state-hover',
focusClass: 'ui-state-focus',
disabledClass: 'ui-state-disabled',
onSubmit: function(filename, extension)
{
this.setFileSizeBox(sizeBox); // designate this element as file size container
},
onComplete: function(filename, response)
{
if (!response) {
alert(filename + 'upload failed');
return false;
}
alert( 'file ' + response.data + ' uploaded successfully ');
// do something with response...
}
});
});
</script>
<div id='uploadButton'>
CSV
</div>
<div id='sizeBox'>
size
</div>
Use php inbuilt function print_r();
print_r($_FILES);
I am trying to send JSON data from a form using the XMLHttpRequest object. I can send the data using the following function. There are no errors displayed in FireBug and the JSON-data in the request is displayed well formed by FireBug.
However, I send the data to echo.php, what simply returns the content:
<?php
print_r($_POST);
print_r($_GET);
foreach (getallheaders() as $name => $value) {
echo "$name: $value\n";
}
echo file_get_contents('php://input');
?>
The POST-array is always empty, but I can see the JSON string returned by file_get_contents. How does that happen? What am I doing wrong?
output of echo.php
Array
(
)
Array
(
)
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: eo,de-de;q=0.8,de;q=0.6,en-us;q=0.4,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Referer: http://localhost/form.html
Content-Length: 88
Cookie: {{..to much data..}}
Pragma: no-cache
Cache-Control: no-cache
{"type":"my_type","comment":"commented"}
the sending function:
function submit(){
var data={};
data.type=document.form.type.value;
data.comment=document.form.comment.value;
//get right XMLHttpRequest object for current browsrer
var x=ajaxFunction();
var string = JSON.stringify(data);
x.open('POST','echo.php',true);
x.setRequestHeader('Content-type','application/json; charset=utf-8');
x.setRequestHeader("Content-length", string.length);
x.setRequestHeader("Connection", "close");
x.onreadystatechange = function(){
if (x.readyState != 4) return;
if (x.status != 200 && x.status != 304) {
alert('HTTP error ' + req.status);
return;
}
data.resp = JSON.parse(x.responseText);
if(data.resp.status=='success'){
alert('That worked!');
}else{
alert('That didn\'t work!');
}
}
x.send(string);
return false; //prevent native form submit
}
PHP does not process JSON requests automatically like it does with form-encoded or multipart requests. If you want to use JSON to send requests to PHP, you're basically doing it correctly with file_get_contents(). If you want to merge those variables into your global $_POST object you can, though I would not recommend doing this as it might be confusing to other developers.
// it's safe to overwrite the $_POST if the content-type is application/json
// because the $_POST var will be empty
$headers = getallheaders();
if ($headers["Content-Type"] == "application/json")
$_POST = json_decode(file_get_contents("php://input"), true) ?: [];
Quick note: you should not be sending a charset with your Content-Type for application/json. This should only be sent with text/* Content-Types.
You forgot to name your variables in the send function.
The good way to use it is
x.send('name1='+string+'&name2=value2');
Given that, I think you will have to change the content-length header. I don't think it is usefull to send it.
One another thing you can do is try with GET method.
You can also try to change your content-type header by that one :
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")