Ok, so in my web app's API I have an incoming HTTP post request.
I would like to pass that POST request on to a different server, without losing the data in the POST header. Is this possible? which type of redirect would I use? php examples?
Edit: The HTTP request is coming from a mobile app, not a web browser.
Thanks!
You could use cURL or sockets to re-post the data, but you can't really redirect it.
POST'ing to a URL with cURL:
$ch = curl_init('http://www.somewhere.com/that/receives/postdata.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
RewriteRule current-page.php http://www.newserver.com/newpage.php [NC,P]
The P on there (proxy) will preserve the POST data. You'll need to turn on the apache proxy module if it isn't already.
I know this is an old question but this may help people who stumble upon this question. You should be able to send an HTTP 307 response code to make the user agent redirect to the new url and continue to use the same method and data. This answer has more details
If the client (ie the mobile app) HTTP library supports this, then you can return HTTP 307 from server which states that "the request should be repeated with another URI ... with the same method". This is essentially a temporary redirect but tells the client to use the the same method, a POST.
The client making the request must be able to respond accordingly to the HTTP 307 response and follow the redirection with the same method - for many libraries this may be an additional flag or setting.
You cannot tell a browser to make a post request through an HTTP header. The location header will redirect, but only for GET or HEAD requests.
You can work around this limitation by displaying a page with a hidden form with the method attribute set to POST and the action set to the URL you want the browser to post to, then automatically submit it on page load. Example:
<body onload="document.getElementById('form').submit();">
<form id="form" action="http://example.com/form_handler.php" method="POST">
<input type="hidden" name="param_1" value="data">
</form>
</body>
Alternately, you can make the POST request on your server and then display the results.
I used the following code to redirect a post. In my case I am using only application/octet-stream content type so make sure you take that into consideration.
$request = file_get_contents ( "php://input" );
$arrContextOptions=array(
"http" => array(
"method" => "POST",
"header" =>
'Content-Type: application/octet-stream'. "\r\n".
'Content-Length: ' . strlen($request) . "\r\n",
"content" => $request,
),
"ssl"=>array(
"allow_self_signed"=>true,
"verify_peer"=>false,
),
);
$arrContextOptions = stream_context_create($arrContextOptions);
header ( "HTTP/1.1" );
header ( "Content-Type: application/octet-stream" );
$result = file_get_contents('http://thenewaddress.yes.it.works', false, $arrContextOptions);
file_put_contents("php://output", $result);
I think the solution I'm about to go with is something like:
<?
$url = 'http://myserver.com/file.php';
foreach ($_POST as $key => $value) {
$text .= (strlen($text) > 0 ? '&' : '');
$text .= $key . '=' . $value;
}
header('Location: ' . $url . '?' . $text);
exit;
?>
Can anyone think of a reason why this is a bad idea?
If you want to take data from a POST request and simply POST it to another server, then use cURL.
--or--
If you want to take data from a POST request and redirect the client to that other server while POSTing the data, then use this method...
Dynamically generate a form with all of the POST data. Something likes this...
echo "<form name=\"someform\" action=\"http://www.somewhereelse.com/someform.whatever\">";
foreach ($_POST as $key=>$value) {
echo "<input type=\"hidden=\" name=\"" . htmlspecialchars($key) . "\" value=\"" . htmlspecialchars($value) . "\" />";
}
echo "</form>";
Then, submit that form with some JavaScript when the page is done loading...
document.forms['someform'].submit();
Related
I am new to JSON data transfer. I want to make a user click on a link in a webpage and that should redirect the user to another page with his login credentials in the url and display it there. Now this all I want to send and receive through JSON . I am working on PHP environment. I am adding a short code on which I am working but not knowing how to proceed exactly.
send.php
<?php
$data = '{ "user" : [
{ "email" : "xyz#gmail.com",
"password" : "xyz#123",
"employee_id" : 77
}
]
} ';
$url_send ="http://localhost/cwmsbi/recieve.php";
$str_data = json_encode($data);
function sendPostData($url_send, $post){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post))
);
$result = curl_exec($ch);
curl_close($ch); // Seems like good practice
return $result;
}
echo " " . sendPostData($url_send, $str_data);
?>
And receive.php
<?php
$json_input_data=json_decode(file_get_contents('php://input'),TRUE);
print_r( $json_input_data);
?>
Now when I am running send.php on my localhost, it displays the data on same page but does not goes to recieve.php.
How this can be achieved? I am curious and in need of this too. How can I run a JSON file and where should i obtain results? Your guidance will be immensely useful to me right now.
First of all i see you are json encoding $data two times (as when it gets defines it is already a json string and then you do $str_data = json_encode($data);).
If you want to achive the change of location with post data too, you can't use curl
(POST data and redirect user by PHP CURL - read this question for further infos) - and i don't think you can do it by php only.
If i was trying to achive what you're trying to achive (and i would never make a page to show login password to users - as it is bad practice to show a password, even in emails), i suggest to set the json string into $_SESSION variable in send.php and redirect with header("Location: http://localhost/cwmsbi/recieve.php") where you get the json data from $_SESSION variable and you print it.
I did not make an example as i think this one perfectly suites you:
https://stackoverflow.com/a/42215249/9606459
Extra hint: even if placing the password in php $_SESSION variable is better than put it in post request, remember you are doing bad practice and at least remember to empty out that json string in $_SESSION variable after you print it.
e.g.:
unset($_SESSION['user_data']);
PHP code:
$fields_string = "";
foreach ($postingfields as $key=>$value) {
$fields_string .= $key . '=' . urlencode($value) . '&';
}
$fields_string = rtrim($fields_string,'&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$client_url);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$response = curl_getinfo( $ch );
curl_close($ch);
$client_url php variable holds the value: https://pcloudtest.com/Default.aspx?cid=99938
$fields_string php variable holds the value: &sid=30&title=Mr&firstname=Charles&surname=Smith
The destination server has been set up to respond with the following HTML:
When I debug (send info to a separate txt file in linux) the value of $result is:
<URL>https://pcloudtest.com/Default.aspx?cid=99938</URL>
ie this is what the destination server is claiming has been sent to them from my end.
In other words, the $client_url is all that is being posted, and not the rest of it (ie the $fields_string) and the full URL that should've been posted should read:
https://pcloudtest.com/Default.aspx?cid=99938&sid=30&title=Mr&firstname=Charles&surname=Smith
I have tried everything I can to figure out why the php curl functions are apparently sending out a shortened URL, ie up to the first occurrence of an ampersand. The code logic I have above has not changed in months and is working for other destination servers.
I might add that the other destination servers where this logic has no issues are http: sites not https:. But I have been reassured by the tech guys on the other end that it definitely has nothing to do with posting to a https site.
Please help. I hope I have outlined my issue clearly enough, and if not, please advise as to more info I can provide.
I need to get the complete output from an aspx site. When the user leaves I will save what's in some specific elements in cookies. The problem is that the aspx is on a domain I don't have access to. I want the output to behave as in an iframe so links need to be clickable but it won't leave my page.
I think of either AJAX with PHP-proxy or an iframe that I can modify content in.
Is this possible?
If it is possible and it involves server-side code I would like to know if there are any free web hosts that support the full code( for example almost every free web host has safe_mode on for PHP).
EDIT: I want to display this page : School scheme. The URL doesn't to change, it just sends requests to the server (think via JavaScript). When the user leaves I will see what's in the select box id="TypeDropDownList" and what's in the select box id="ScheduleIDDropDownList".
When the user returns to my page I will print those values to the page via URL like this "http://www.novasoftware.se/webviewer/(S(lv1isca2txx1bu45c3kvic45))/design1.aspx?schoolid=27500&code=82820&type=" + type + "&id=" + id + "
I tried several php proxy scripts on 000webhost before I posted here.
for example this :
<?php
ob_start();
function logf($message) {
$fd = fopen('proxy.log', "a");
fwrite($fd, $message . "\n");
fclose($fd);
}
?>
<?
$url = $_REQUEST['url'];
logf($url);
$curl_handle = curl_init($url);
curl_setopt($curl_handle, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, "Owen's AJAX Proxy");
$content = curl_exec($curl_handle);
$content_type = curl_getinfo($curl_handle, CURLINFO_CONTENT_TYPE);
curl_close($curl_handle);
header("Content-Type: $content_type");
echo $content;
ob_flush();
?>
But it returns Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in /home/a5379897/public_html/ajax-proxy.php on line 16
I tried to contact them about this because they say they have cURL enabled but they haven't responded yet.
I think it would be possible to just display the two select boxes when the user first visit the page. When options is selected it will make an iframe show the right page by passing "http://www.novasoftware.se/webviewer/(S(lv1isca2txx1bu45c3kvic45))/design1.aspx?schoolid=27500&code=82820&type=" + type + "&id=" + id + " to the src attribute.
The problem with that is that I will need to retrieve the select boxes someway and I will have the same problem.
You would need to use PHP as Javascript doesn't doesn't allow cross domain requests. Your PHP code would literally grab the page the client wants, process it (changing link's href to your page with a get variable of the page the original href links to). When they click the link they will be sent to the same page they are on now but the page will grab the new page and return that(processing that page too) and so on.
000webhost are a nice free webhost that allow you to do most of PHP's functions and don't put adverts on your site.
To get the whole aspx output as a string to manipulate, you can use file_get_contents(http://yoursite.com/yourpage.aspx);
For best results, open a stream as the context via http.
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents('http://www.example.com/', false, $context);
?>
Thanks to greg I could create this script that gets the page.
<html>
<head>
</head>
<body>
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
$host = 'http://www.novasoftware.se/webviewer/(S(bkjwdqntqzife4251x4sdx45))/';
$url = '/design1.aspx?schoolid=27500&code=82820&type=3&id={7294F285-A5CB-47D6-B268-E950CA205560}';
$changetothis='src="'.$host;
// Open the file using the HTTP headers set above
$file = file_get_contents($host.$url, false, $context);
$changed = str_replace('src="', $changetothis,$file);
echo $changed;
?>
</body>
</html>
API integration description
The API needs a form to be posted to the API URL with some input fields and a customer token. The API processes and then posts response to a callback.php file on my server. I can access the posted vals using $_POST in that file. That's all about the existing method and it works fine.
Requirement
To hide the customer token value from being seen from client side. So I started with sending server side post request.
Problem
I tried with many options but the callback is not happening -
1) CURL method
$ch = curl_init(API_URL);
$encoded = '';
$_postArray['customer_token'] = API_CUSTOMER_TOKEN;
foreach($_postArray as $name => $value)
{
$encoded .= urlencode($name).'='.urlencode($value).'&';
}
// chop off last ampersand
$encoded = substr($encoded, 0, strlen($encoded)-1);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
$resp = curl_exec($ch);
curl_close($ch);
echo $resp;
$resp echoes 1 if the line curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); is removed but the callback does not happen. I am setting a session variable in the callback script to verify.Is it needed that the API be synchronous in order to use curl method, so that curl_exec returns the response?
2) without CURL as given in Posting parameters to a url using the POST method without using a form
But the callback is not happening.
I tried with the following code too, but looks like my pecl is not installed properly because the HttpRequest() is not defined.
$req = new HttpRequest($apiUrl, HttpRequest::METH_POST);
$req->addQueryData($params);
try
{
$r->send();
if ($r->getResponseCode() == 200)
{
echo "success";
// success!
}
else
{
echo "failure";
// got to the API, the API returned perhaps a RESTful response code like 404
}
}
catch (HttpException $ex)
{
// couldn't get to the API (probably)
}
Please help me out! I just need to easily send a server side post request and get the response in the callback file.
Try to debug your request using the curl_get_info() function:
$header = curl_getinfo($ch);
print_r($header);
Your request might be OK but it my result in an error 404.
EDIT: If you want to perform a post request, add this to your code:
curl_setopt($ch, CURLOPT_POST, true);
EDIT: Something else I mentioned at your code: You used a '1' at the 'CURLOPT_RETURNTRANSFER' but is should be 'true':
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
At least this is how I usually do it, and you never know if the function will also understand a '1' as 'true';
EDIT: The real problem: I copy-pasted your source and used it on one of my pages getting this error:
Warning: urlencode() expects parameter 1 to be string, array given in C:\xampp\htdocs\phptests\test.php on line 8
The error is in this line:
foreach($_postArray as $name => $value)
$_postArray is an array with one value holding the other values and you need either another foreach or you simple use this:
foreach($_postArray['customer_token'] as $name => $value)
As discussed in the previous question, the callback is an entirely separate thing from your request. The callback also will not have your session variables, because the remote API is acting as the client to the callback script and has its own session.
You should really show some API documentation here. Maybe we're misunderstanding each other but as far as I can see, what you are trying to do (get the callback value in the initial CURL request) is futile, and doesn't become any less futile by asking twice.
Using PHP and CURL (unless there is a better alternative then CURL in this case), is it possible to have a php function handle the header response before downloading the file?
For example:
I have a script that downloads and processes urls supplied by the user. I would like to add a check so that if the file is not valid for my process (not a text file, too large, etc),the CURL request would be cancelled before the server wastes time downloading the file.
Update: Solution
PEAR class HTTP_Request2: http://pear.php.net/package/HTTP_Request2/
Gives you the ability to set observers to the connection and throw exceptions to cancel anytime. Works perfectly for my needs!
Using cURL, do a HTTP HEAD request to check the headers, then if it is valid (the status is 200) do the full HTTP GET request.
The basic option you must set is CURLOPT_NOBODY, which changes the requested to the type HEAD
curl_setopt($ch, CURLOPT_NOBODY, true);
Then after executing the query, you need to check the return status which can be done using curl_getinfo()
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
I know this is an old topic but just in case people comes here in the future.
With CURL, you can use CURLOPT_WRITEFUNCTION, who let's you place a callback that will be called as soon as the body response starts coming and needs to be written. In that moment you can read the headers and cancel the process and the body will not be downloaded. All in one request.
For a deeper look and code examples see PHP/Curl: inspecting response headers before downloading body
This is an example how you can solve it:
// Include the Auth string in the headers
// Together with the API version being used
$headers = array(
"Authorization: GoogleLogin auth=" . $auth,
"GData-Version: 3.0",
);
// Make the request
curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/default/private/full");
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($curl);
curl_close($curl);
// Parse the response
$response = simplexml_load_string($response);
// Output data
foreach($response->entry as $file)
{
//now you can do what ever if file type is a txt
//if($file->title =="txt")
// do something
else
// do soething
echo "File: " . $file->title . "<br />";
echo "Type: " . $file->content["type"] . "<br />";
echo "Author: " . $file->author->name . "<br /><br />";
}