I use SlimFramework
When i run my script locali with xampp it works fine.
But i uploaded the script to the server and now it cone the error that the header was not set.
XHR does not allow payloads for GET request.
or change a method definition in settings.
Here the script in angular
$rootScope.globals = $cookies.getObject('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.token;
}
$rootScope.$on('$locationChangeStart', function (event, next, current) {
var restrictedPage = $.inArray($location.path(), ['/login', '/register', '/password']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage) {
if (!loggedIn) {
$location.path('/login');
} else {
UserService.checkToken($rootScope.globals.currentUser.token)
.then(function (response) {
if (!response.success) {
$location.path('/login');
}
});
}
}
});
function checkToken(token) {
return $http.get('api/v1/token').then(handleCallback, handleCallback);
}
function handleCallback(res) {
console.log(res);
return res.data;
}
And here the script with SlimFramework
$config['displayErrorDetails'] = true;
$config['addContentLengthHeader'] = false;
$config['determineRouteBeforeAppMiddleware'] = true;
$app = new \Slim\App(["settings" => $config]);
$container = $app->getContainer();
// This is the middleware
// It will add the Access-Control-Allow-Methods header to every request
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
});
$app->get('/token', function ($request, $response){
$token = $request->getHeaderLine('Authorization');
if($token){
$db = new DbOperation();
if($db->checkAuthentication($token)){
$return = $response->withJson(["success"=> true], 200);
} else {
$return = $response->withJson([
"success"=> false,
"message"=>'Invalid token'
], 403);
}
} else {
$return = $response->withJson([
"success"=> false,
"message"=>'Header not set.'
], 403);
}
return $return;
});
Whats my Problem?
Everyone knows?
Thx
UPDATE:
Get request
The response from API testing
HTTP/1.1 403 Forbidden
Server: nginx
Date: Mon, 27 Mar 2017 11:57:27 GMT
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.6.30
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization
Access-Control-Allow-Methods: GET
X-Powered-By: PleskLin
if you want to open the api to cors call to every possible origin(test only) try this:
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
});
Or there is this Middleware that do the same: https://github.com/palanik/CorsSlim
If you are not sure what is the header name generated by NG, you can debug the header sent to SLIM. In SLIM, it can be done like this:
$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
echo $name . ": " . implode(", ", $values);
}
Im using jquery, I set token in header globally, like this:
$.ajaxPrefilter(function( options, oriOptions, jqXHR ) {
jqXHR.setRequestHeader("Authorization", sessionStorage.token);
});
That will send a token with a header name:
HTTP_AUTHORIZATION
To get specific header variable:
$token_array = $request->getHeader('HTTP_AUTHORIZATION');
if (count($token_array) == 0) {
$data = Array(
"jwt_status" => "token_not_exist"
);
return $response->withJson($data, 401)
->withHeader('Content-type', 'application/json');
}
$token = $token_array[0];
Related
This question already has answers here:
Receive JSON POST with PHP
(12 answers)
Closed 8 months ago.
I am trying to experiment with Redux Toolkit Query mutations.
What I have now at the front-end:
import { createApi, fetchBaseQuery } from "#reduxjs/toolkit/query/react";
export const postApi = createApi({
reducerPath: "postApi",
baseQuery: fetchBaseQuery({
baseUrl: "https://webcodingcenter.com/shared/",
prepareHeaders: (headers, { getState }) => {
headers.set("Content-Type", "application/json");
return headers;
}
}),
endpoints: (builder) => ({
getPost: builder.query({
query: (id) => `get_post.php?id=${id}` // expects a JSON response
}),
updatePost: builder.mutation({ // <-- attention here
query: (body) => {
console.log(123, body);
return {
url: `update_post.php`,
method: "POST",
body
};
}
})
})
});
// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetPostQuery, useUpdatePostMutation } = postApi;
And the back end (update_post.php):
<?php
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header("HTTP/1.1 200 OK");
die();
}
$str="HELLO WORLD";
$r="";
for ($i = 0; $i < strlen($str); $i++){
if (rand(0,100)>50) $r .= strtoupper($str[$i]);
else $r .= strtolower($str[$i]);
}
file_put_contents("data".$_POST["id"].".txt",$r);
echo json_encode($_POST);
//echo json_encode(array("post"=>$r));
?>
As you can see from the Code Sandbox here, $_POST is always empty. How can I pass the data to $_POST?
This solves it:
$data = json_decode(file_get_contents('php://input'), true);
Given the following code:
fetch(mockproxy+myphp.php,{
method: 'POST',
headers:{'Token':token["token"]},
body: name,
}).then((response) => response.json())
.then((json)=>{
toast.success(JSON.stringify(json));
})
.catch((err) => {
toast.error(JSON.stringify(err));
})
}
mockproxy is helping bypass CORSS. The file looks like this:
const corsAnywhere = require('cors-anywhere');
const express = require('express');
const apicache = require('apicache');
const expressHttpProxy = require('express-http-proxy');
const CORS_PROXY_PORT = 5000;
// Create CORS Anywhere server
corsAnywhere.createServer({}).listen(CORS_PROXY_PORT, () => {
console.log(
`Internal CORS Anywhere server started at port ${CORS_PROXY_PORT}`
);
});
// Create express Cache server
let app = express();
// Register cache middleware for GET and OPTIONS verbs
app.get('/*', cacheMiddleware());
app.options('/*', cacheMiddleware());
// Proxy to CORS server when request misses cache
app.use(expressHttpProxy(`localhost:${CORS_PROXY_PORT}`));
const APP_PORT = process.env.PORT || 5080;
app.listen(APP_PORT, () => {
console.log(`External CORS cache server started at port ${APP_PORT}`);
});
/**
* Construct the caching middleware
*/
function cacheMiddleware() {
const cacheOptions = {
statusCodes: { include: [200] },
defaultDuration: 60000,
appendKey: (req, res) => req.method
};
let cacheMiddleware = apicache.options(cacheOptions).middleware();
return cacheMiddleware;
}
And the server is a shared server where I upload the PHP files so they can access to the DB. The php receives the data and give a response when I use postman but not when I execute the fetch from the dev website, I'm using react, I think it doesn't matter in this case.
The PHP file:
<?php
$headers = apache_request_headers();
header("Access-Control-Allow-Origin: *, ");
header("Access-Control-Allow-Methods: HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header("HTTP/1.1 200 OK");
exit;
}
if (isset($_POST["name"])) {
echo json_encode(" name" . $_POST["name"]); //returned on postman
}else{
echo json_encode("no name"); //returned on development.
}
exit;
So this is a code i use when i want to fetch all data from a form. You can obviously not loop through all forms like i do below but just your single form.
// Query all forms in the DOM or a specific one if you want
const forms = document.querySelectorAll('form');
// Loop through them
forms.forEach((form) => {
// if method is post
if (form.method === 'post') {
form.addEventListener('submit', (event) => {
// prevent default submit
event.preventDefault();
// prepare the data
let data = new FormData(form);
// fetch using the form's
fetch(form.action, {
method: 'post',
body: data,
})
// get the text() from the Response object
.then(response => response.text())
.then(text => {
// Display it in the result div
document.getElementById('result').innerHTML = text;
})
}, false);
// if not post (get really)
} else {
form.addEventListener('submit', (event) => {
// prevent default submit
event.preventDefault();
// build the URL query params from the submitted data
const data = new URLSearchParams(new FormData(form).entries());
// Fetch, URL is formed from the action, append ? and then the query params
fetch(form.action + '?' + data)
// get the text() from the Response object
.then(response => response.text())
.then(text => {
// Display it in the result div
document.getElementById('result').innerHTML = text;
})
}, false);
}
});
I Am trying to make a simple login check , using angular 4 , php my sql .
Now i am able to send the details to the php , but i am not able to receive the status after it , i have no idea why.
Simply, i want to check if the username and password are correct, then return some json , else , return false result.
Help please.
Angular :
import { Injectable } from '#angular/core';
import { Http, Response ,RequestOptions,Headers} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'
#Injectable()
export class appService {
postResponse:any ;
status;
constructor(private http:Http) { }
insertData() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://localhost:80/angularsql/sql.php',JSON.stringify({firstName:'Joe',lastName:'Smith333'}),{headers:headers})
.map((res: Response) => res.json())
.subscribe((res:'') => this.postResponse = res);
}
}
PHP
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT, GET, POST");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
$data = json_decode( file_get_contents('php://input'),true );
$fname = $data['firstName'];
$lname = $data['lastName'];
$con = new mysqli('localhost','root','','angular');
if($fname=='anan' && $lname=='kassis') {
$sql = "insert into users_tbl(firstName,lastName) values('".$fname."','".$lname."')";
$result = $con->query($sql);
$data = [ "status" => "CORRECT" ];
echo json_encode($data);
}
else {
$data = [ "status" => "wrong details inserted" ];
echo json_encode($data);
}
//echo $result;
?>
I think you should change
subscribe((res:'') => this.postResponse = res);
to
subscribe(res: any =>
{
this.postResponse = res);
console.log(res.status)
}
Here, res will be an object and you can console.log(res.status)
Edit: You cannot have the console.log after the subscribe call, because at this stage the http call has not received a response yet.
Other things to consider:
And probably set json type headers in your php response
header('Content-Type: application/json');
Also, you should use parametrized queries (like PDO) when querying your database
I think this line is the issue:
.subscribe((res:'') => this.postResponse = res);
Change your call into:
insertData(): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://localhost:80/angularsql/sql.php', JSON.stringify({
firstName: 'Joe',
lastName: 'Smith333'
}), { headers: headers })
.map(res => res.json())
.catch((error: any) => Observable.throw(
{ message: error.json().message, details: error.json().details }));
}
You should subscribe to the insertData() method. And in your .post() you map the result and you catch the errrors (if any).
I have an API built with PHP Slim Framework 3 and testing the API with Postman everything is working great but when I put the app on the server and tried to make an Ajax Call I've got this message:
Failed to load https://api.mydomain.net/usuario/autenticar?xAuthClienteID=2&xAuthChaveApi=3851b1ae73ca0ca6e3c24a0256a80ace&login=admin&senha=teste: Redirect from 'https://api.maydomain.net/usuario/autenticar?xAuthClienteID=2&xAuthChaveApi=3851b1ae73ca0ca6e3c24a0256a80ace&login=admin&senha=teste' to 'https://api.mydomain.net/404.html' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
I've looked up Slim docs on how to enable CORS on my server and applied it on the function I use to return JSON. It looks like this:
public function withCustomJson($meta = null, $data = null)
{
if (isset($data)) {
$finalResponse['data'] = $data;
}
$finalResponse['meta'] = array(
'status' => (isset($meta['status']) ? $meta['status'] : null),
'message' => (isset($meta['message']) ? mb_convert_encoding($meta['message'], "UTF-8", "auto") : null)
);
$response = $this->withBody(new Body(fopen('php://temp', 'r+')));
$response->body->write($json = json_encode($finalResponse));
// Ensure that the json encoding passed successfully
if ($json === false) {
throw new \RuntimeException(json_last_error_msg(), json_last_error());
}
//Allowing CORS as Slim docs states
$responseWithJson = $response->withHeader('Content-Type', 'application/json;charset=utf-8')
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
if (isset($meta['codStatus'])) {
return $responseWithJson->withStatus($meta['codStatus']);
}
return $responseWithJson;
}
And here's what my Ajax call looks like:
<script type="text/javascript">
try {
$.ajax({
url: 'https://api.mydomain.net/usuario/autenticar',
type: 'GET',
dataType: 'json',
data: {
xAuthClienteID:'2',
xAuthChaveApi: '3851b1ae73ca0ca6e3c24a0256a80ace',
login: 'admin',
senha: 'teste'
},
ContentType: 'application/json',
success: function(response){
console.log(response);
},
error: function(err){
console.log(err);
}
});
}
catch(err) {
alert(err);
}
</script>
So, what am I doing wrong? Appreciate any help.
This is propably something simple and obvious but I can't see where the problem is. After some research I found that in order to enable CORS in laravel 4 oen should add the following to the filters.php:
App::before(function($request)
{
if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
$statusCode = 204;
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, X-Requested-With',
'Access-Control-Allow-Credentials' => 'true'
];
return Response::make(null, $statusCode, $headers);
}
});
App::after(function($request, $response)
{
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization, X-Requested-With');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
return $response;
});
So to my mind when one does this in angularjs:
app.factory('RestFactory', function ($http) {
var BASE_URL = 'url_to_the_site';
return {
get: function (target) {
return $http({method: 'GET', url: BASE_URL + target});
},
post: function (target, data) {
return $http.post(BASE_URL + target, data);
}
};
});
It should work right? When running Laravel 4 in localhost:8000 at development mode it seems to work. However when I transfer the Laravel to my site and try accessing the site url all I get is:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
So What am I doing wrong here? It works on local, the BASE_URL also works when going to the url with a browser so what am I missing here?