Hello I'm trying to send mail via php with mandrill, but have problems with preflight request - sending email twice, but first time without values from request
here is php code:
$method = $_SERVER['REQUEST_METHOD'];
try {
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");
die();
} else {
$user_request->update_request_status();
$mandrill_request_data = get_mandril_request_data($user_request);
email($mandrill_request_data);
die();
}
} catch (Exception $e) {
echo($e->getMessage());
}
I've tried this way, but without solving problem.
Related
I have an sms API which is called in a PHP file ,which is used in Android as well as in PWA application. This API was previously installed in a Linux based server on Apache and recently shifted to a windows based server to IIS. It is working fine in Linux based server but after shifting to windows based server , API is only giving false response even though all parameters has been provided. Any help would be really appreciated as I'm stuck in this from a week . In android studio I'm getting a 400 response when calling this API.
im unable trace the issue.
<?php
ini_set('soap.wsdl_cache_enabled', 0);
ini_set('soap.wsdl_cache_ttl', 0);
ini_set('default_socket_timeout', 15);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, DELETE, PUT, PATCH, OPTIONS');
header('Content-Length: 0');
header('Content-Type: text/plain');
die();
}
header("Access-Control-Allow-Origin: *");
Cache-Control, Pragma, Accept, Accept-Encoding");
header("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE");
header('Content-Type: application/json');
$params = json_decode(file_get_contents("php://input"), TRUE);
if (empty($params)) {
$params = $_POST;
}
$invalid_params = (empty($params) || empty($params['username']) || empty($params['password'] || $params['senderid']) || empty($params['message']) || empty($params['mobilenumber']));
if ($invalid_params) {
http_response_code(200);
echo json_encode(['status' => false, 'msg' => 'Invalid Parameters']);
exit;
} else {
try {
$params = json_decode(file_get_contents("php://input"), TRUE);
if (empty($params)) {
$params = $_POST;
}
$url = "http://ip/smsapi/httpapi.jsp?username=" . urlencode($params['username']) . "&password=" . $params['password'] . "&from=" . urlencode($params['senderid']) . "&to=" . urlencode($params['mobilenumber']) . "&text=" . urlencode($params['message']) . "&coding=0&flash=0";
// echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//echo $code;
curl_close($ch);
if ($code == 200) {
$xml = simplexml_load_string($result);
$json = json_encode($xml);
$arr = json_decode($json, true);
if (!empty($arr['ack_id'])) {
response_handler();
} else {
error_handler();
}
} else {
error_handler();
}
} catch (Exception $e) {
error_handler();
}
}
function error_handler()
{
http_response_code(200);
echo json_encode(['status' => false, 'msg' => 'Failed to send otp']);
exit;
}
function response_handler()
{
http_response_code(200);
echo json_encode(['status' => true, 'msg' => 'Otp Send Successfully']);
exit;
}
So I'm trying to make an endpoint to access my database with and it works just fine in postman, but when calling the GET request on my website i get a CORS error:
Query for foreign site blocked: The same origin policy does not allow remote resource reading http://IPGOESHERE/cordova/endpoint/log.php?id=-1. (Cause: The CORS query failed).)
I've tried googling but was unable to find anything useful.
My server-sided code is in 2 files which i have included below:
models/Log.php:
class Log {
// database connection and table name
private $conn;
private $table_name = "logging";
// object properties
public $ID;
public $UserID;
public $Handling;
public $Date;
// constructor with $db as database connection
public function __construct($db) {
$this->conn = $db;
}
// read products
function read($id)
{
$query = "SELECT * FROM " . $this->table_name;
if ($id != '-1') {
// select query
$query .= " WHERE logging.ID = ".$id;
}
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
return $stmt;
}
}
log.php
// required headers
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 1000");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
header("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE");
header("Content-Type: application/json; charset=UTF-8");
// database connection will be here
include_once '../database.inc';
include_once '../models/Log.php';
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$id = $_GET['id'];
$database = new Database();
$db = $database->getConnection();
$Log = new Log($db);
// query products
$stmt = $Log->read($id);
$num = $stmt->rowCount();
// check if more than 0 record found
if ($num > 0) {
$products_arr = array();
$products_arr["records"] = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
extract($row);
$product_item = array(
"ID" => $ID,
"UserID" => $UserID,
"Handling" => $Handling,
"Date" => $Date,
);
array_push($products_arr["records"], $product_item);
}
// set response code - 200 OK
http_response_code(200);
// show products data in json format
echo json_encode($products_arr);
} else {
// set response code - 404 Not found
http_response_code(404);
// tell the user no products found
echo json_encode(
array("message" => "No log found")
);
}
}
Turns out it was due to php not allowing me to use the class name "Log" renamed everything called log & it now works flawlessly.
Using a XSRF-TOKEN to prevent against XSRF attacks as I'm passing a JWT threw a cookie for my Angular app. Here is what my HttpInterceptor is looking like.
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headerName = "XSRF-TOKEN";
const respHeaderName = "X-XSRF-TOKEN";
let token = this.tokenExtractor.getToken() as string;
if (token !== null && !req.headers.has(headerName)) {
req = req.clone({ headers: req.headers.set(respHeaderName, token) });
}
return next.handle(req);
}
This causes a 400 Bad Request error to pop up in my console with a message reading: Response for preflight does not have HTTP ok status. If I comment out the line of code where the request is cloned, the error goes away, and my HTTP request goes through perfectly.
My headers in my .htaccess look like this.
Header set Access-Control-Allow-Origin "http://localhost:4200"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Headers "Content-Type"
Header set Access-Control-Allow-Headers "Authorization"
Header set Access-Control-Allow-Headers "X-XSRF-TOKEN"
Header set Access-Control-Expose-Headers: "Authorization"
Any help would be greatly appreciated, thanks.
EDIT 1: A MCVE of my PHP code
$return = array();
if (isset($_POST["email"]) && isset($_POST["password"])) {
header("HTTP/1.0 200");
$return["msg"] = "random";
echo json_encode($return);
} else {
header("HTTP/1.0 400");
$return["error_message"] = "HTTP Post variables are not set!";
$return["friendly_error_message"] = "Client error!";
echo json_encode($return);
}
exit();
And my verify() function in my Angular service.
verify(email: string, password: string): Observable<JSON> {
let headers = new HttpHeaders()
headers = headers.set("Content-Type", "application/x-www-form-urlencoded");
let body = new HttpParams();
body = body.set("email", email);
body = body.set("password", password);
return this.http.post<JSON>("http://localhost:80/verify", body, { headers: headers, withCredentials: true, observe: "response" }).pipe(
map(res => {
return res.body;
}),
catchError(this.handleError)
);
}
I've been testing with a "XSRF-TOKEN" session cookie by commenting/un-commenting a line of PHP code. When the session cookie is active, this error happens.
When I delete the cookie, I obviously don't have this problem because the req.clone() function never goes through as the conditional isn't met.
Your server side code is not correctly responding to the preflight request for XSRF / CSRF workflow. You have to return a "200 OK" response to an OPTIONS request so your Angular plugin works:
<?php
$return = array();
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// instead of doing that in .htaccess
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type");
header("Access-Control-Allow-Headers: Authorization");
header("Access-Control-Allow-Headers: X-XSRF-TOKEN");
header("Access-Control-Expose-Headers: Authorization");
// a 200 OK response to preflight with empty body
header("HTTP/1.0 200");
} elseif (isset($_POST["email"]) && isset($_POST["password"])) {
// presuming all request that are not a preflight
// must be a POST request.
header("HTTP/1.0 200");
$return["msg"] = "random";
echo json_encode($return);
} else {
header("HTTP/1.0 400");
$return["error_message"] = "HTTP Post variables are not set!";
$return["friendly_error_message"] = "Client error!";
echo json_encode($return);
}
exit();
we are programming a Restful API to be called from an ionic app. We are sending from angular service with this code:
.service('ServiceName', function($http) {
return {
borrarAlumno: function(par) {
var link = "http://localhost/ws/index.php";
return $http.delete(link, {
id: par.id
})
}
}
})
When we try to read id parameter from php we dont get anything. This is the code we are using:
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'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, DELETE, PUT, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers:{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
$input = file_get_contents('php://input');
print_r($_SERVER['REQUEST_METHOD']);
exit();
We have tried with similar code to get parameters with PUT, GET and POST methods and it worked.
Any help would be appreciated.
Edit:
This php is called form another PHP:
class AlumnosAPI
{
public function API()
{
header('Content-Type: application/JSON');
$method = $_SERVER['REQUEST_METHOD'];
switch ($method)
{
case 'GET':
include('get.php');
break;
case 'POST':
include('post.php');
break;
case 'PUT':
include('put.php');
break;
case 'DELETE':
include('delete.php');
break;
default:
echo 'NOT SUPPORTED';
break;
}
}
}
Edit 2: full code of delete.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'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS')
{
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, DELETE, PUT, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers:{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
$valor['borrado'] = 0;
include('conexion.php');
$id = "";
//parse_str(file_get_contents('php://input'), $delete);
$input = file_get_contents('php://input');
print_r($input);
exit();
foreach (array_keys($delete) as $key)
{
$$key = $delete[$key];
}
if ($id != "")
{
//PREPARAMOS LA SENTENCIA SQL
$sql = "DELETE FROM Alumnado WHERE `ID`=?";
$resultado1=$conexion->prepare($sql);
$resultado1->bind_param('i', $id);
$resultado1->execute();
$valor['borrado'] = $resultado1->affected_rows;
}
$datos=json_encode($valor);
echo $datos;
Angular doesn't send a request body for DELETE so you're going to have to read id from the URL.
.service('ServiceName', function($http) {
return {
borrarAlumno: function(par) {
var link = "http://localhost/ws/index.php";
return $http.delete(link, {
params : {id: par.id}
})
}
}
})
get the id via $_GET['id'] instead of file_get_contents('php://input');
Following is my php code:
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
include 'dbconnection.php';
try{
if (isset($_GET['term'])){
$return_arr = array();
$stmt = $conn->prepare('SELECT JOBNO FROM PRTJOBHD WHERE JOBNO LIKE :term');
$stmt->execute(array('term' => '%'.$_GET['term'].'%'));
while($row = $stmt->fetch()) {
$return_arr[] = $row['JOBNO'];
}
}
}catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
/* Toss back results as json encoded array. */
echo json_encode($return_arr);
?>
I'm getting a error that "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://192.168.0.102/ipack/search.php?term=a. (Reason: CORS header 'Access-Control-Allow-Origin' missing)." while running on browser.