Receiving http request with php script (from nginx proxy pass) - php

I'm trying to use data sent by nginx's proxy_pass directive in a php script.
Normally this is done with a proper web server, but I thought this might be a simpler and more reliable approach for very basic use cases.
This is the relevant nginx configuration:
location ~ \.htm$ {
post_action /test;
}
location = /test {
internal;
proxy_method POST;
proxy_pass https://some.website/test.php;
}
This is the php script:
<?php
$headers = getallheaders();
$useragent = $headers['User-Agent'];
$languages = $headers['Accept-Language'];
$md5 = md5($useragent + $languages);
$endpoint = "https://some.webserver/endpoint";
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $md5);
curl_exec($ch);
curl_close($ch);
So, the intended functionality is that whenever a .htm page is loaded, the data is proxy_passed to some.website, processed and then sent further to some.webserver.
This doesn't seem to work... however:
If I use Postman to send a Post request to https://some.website/test.php, it works.
If I proxy_pass directly to https://some.webserver/endpoint, it works.
So what am I missing?

Turns out it was a ssl issue, adding proxy_ssl_server_name on; to the nginx block fixed it.

Related

Parsing Redirect Response Codes From Redirect URL - PHP

Thank you for your time.
My purpose for posting this question was to see how I can approach the problem of parsing the authorization code I get from the redirect to use that code in a subsequent function to get the oauth bearer token.
What libraries can I use similar to python's request module and web module to achieve the same goal as the following code?
class ILToken(object):
def GET(self):
form = web.input(code=None, scope=None)
As an outcome, here is the following example. I have a redirect url set to "http://redirect_example.com/oauth/". When I click a button, the instant login link ("https://api.provider.com/oauth/authorize?response_type=code&redirect_uri=http://redirect_example.com/oauth/...") redirects me to "http://redirect_example.com/oauth/?code=ExampleAuthCode".
I've tried making use of the curl library in php with no positive progress using code similar to the following.
Code
# Initialize curl request parameters
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, env('INSTANT_LOGIN_URI'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, TRUE); // We'll parse redirect url from header.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
# Set variables and execute
$output = curl_exec($ch);
$response_code = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
$redirect = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
curl_close($ch);
# Print Results
print $redirect;
Related articles say to set FOLLOWLOCATION to true and use the CURLINFO_EFFEFCTIVE_URL variable to return the code. This did not work for me. I am using php v7.4 on an ubuntu machine. The php app is using the laravel framework and loading behind an nginx v1.21 web server.
How can I get the destination URL using cURL?
PHP CURL redirect

$_POST/$_GET Submitted URL too large

I have php scripts to migrate data from one database do another. In one script I call one another to Get the data from the original database, and then it sends it to another. Something like this:
migrateData.php <---> getData.php
and then migrateData.php <---> putData.php
In putData.php im using $_GET, but when its too many Data I get the error saying "The length of the requested URL exceeds the capacity limit of this server".
I've seen people saying to use $_POST, but i'm not really sure about it.
My migrateData.php:
<?php
echo "Migration";
$url = "http://localhost/mig/getData.php";
$client = curl_init($url);
curl_setopt($client,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($client);
echo "<br>";
echo "<br>";
echo $response;
$url = "http://localhost/mig/putData.php?data=".$response;
$url = str_replace ( ' ', '%20', $url);
$client = curl_init($url);
curl_setopt($client,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($client);
echo $response;
?>
Any help would be appreciated
Yes when you send a get request to the server (apache, nginx), it may limit the allowed size of a client's HTTP request-line (e.g. ) and the HTTP request header field size.
For example if you have access to the server and its an Apache server you can increase the Apache limits for limit request line and limit request field size.
In case of nginx, you can increase the large_client_header_buffers parameter in nginx.conf.
Using POST method will send the fields outside of the client's HTTP request-line, effectively bypassing the server constraint.
Actually POST request are also limited but the default size is bigger.
Using POST or PUT method is recommended instead of changing the server config.
<?php
//Your code to get the response here
// ...
$data = ['data' => $response];
// Prepare new cURL resource
$ch = curl_init('http://localhost/mig/putData.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// Submit the POST request
$result = curl_exec($ch);
// Close cURL session handle
curl_close($ch);
//Output the result
echo $result;
?>
Apache's max $_GET request length is 8190 bytes (https://stackoverflow.com/a/1289611/575047) so trying to send heaps of data in a GET request is a bad idea because it might get cut off.
POST is ideal. By default, apache sets post_max_size to 8mb I believe.
To POST, you just need to add these lines I believe to your putData curl
curl_setopt($client, CURLOPT_POST, 1);
curl_setopt($client, CURLOPT_POSTFIELDS, $response);

Redirecting a client's request to a second server to get it served and back to the first server

There is a website hosted on server A. This host is a shared host with limited capabilities. Then, there is a second server which is dedicated and has all required functionalities and capabilities.
I want to redirect the client request as is, to the second server, to get it served, processed, and then send back the required information back to the server one. Here is the scenario:
1- User send a request for www.site.com
2- www.site.com receives the request, send the client information to the second server with a different domain, for instance mysecondsite.com, and the receives some packs of data.
3- site.com renders the page (or serve the request) with the data returned from mysecondsite.com
This probably should be done with APACHE since I need the request to be sent before the PHP's processing, since I want some certain raw information to be sent.
Now, for those who might be curious why I should do this?
As you know, I install extension or tools which does certain things which shared-hosting never install or allow. I have a dedicated server which is optimized by many tools and extensions.
For instance, assume that I have written a PHP extension which serves the user request and provide an array of information about its agents, versions, operating systems etc. Using the scenario above, I then send back information information from my dedicated server back to the request's source server.
The example above is only feasible if the host be dedicated. Which in many cases of my clients, is not.
I did something similar and used curl for it:
$url = "http://secondserver.com?p=SOMESECRET";
$post['data[expire]'] = '2014-07-04';
$post['data[date]']= date("d.m.Y", time());
$post['data[count]']= $data['count'];
//initialize session
$ch = curl_init($url);
//the generated pdf from the external server
$tmppdf = tempnam($_SERVER['DOCUMENT_ROOT']."/cache/","pdf");
$fp = fopen($tmppdf, "a+b");
//session options
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
//curl_setopt($ch, CURLOPT_HEADER, false);
//execute the request
curl_exec($ch);
//close the session and filepointer
curl_close($ch);
fclose($fp);
and on the server second server side:
$privateKey = "SOMESECRET";
if($privateKey != $_GET['p']) return;
$yourPassedData = $_POST['data'];
and you are done.
Additional:
If you want to serve directly the response from another server you can use the following combination:
$post['data[headers]'] = getallheaders();
//initialize session
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
return $response;
for the part where you want to fetch the request header, please refer to:
http://php.net/manual/en/function.getallheaders.php
I think Apache's mod_rewrite module does not work in this scenario, because you cannot forward to another domain without making it visible to the client.
However, you could
simply
receive the request on the first server
use PHP's file_get_contents() function, using a URL including all the information that is necessary for the special request
parse the request on the second server and echo the response e.g. in JSON format
parse the response of the request on the first server
Instead if file_get_contents(), you could also use PHP's cURL (if available on the first server), since it is more flexible and offers more possibilities.

get php virtual() response headers

The following makes a sub-request and outputs its body HTTP response content:
<?php
if (condition()) {
virtual('/vh/test.php');
}
?>
Is there a way to get its response headers?
My goal is to forward my request (with request headers) to other location on other host, which is accomplished with Apache ProxyPass directive, and set its response (headers and content) as the response to my request.
So my server would act as a reverse proxy. But it will test some condition which requires php context to be done, before forwarding the request.
Lets say, that current page has own original headers. By using virtual() you are forcing apache to perform sub-request, which generates additional virtual headers. You might get difference of those two header groups (by saving each with apache_response_headers()) by array_diff():
<?php
$original = apache_response_headers();
virtual('somepage.php');
$virtual = apache_response_headers();
$difference = array_diff($virtual, $original);
print_r($difference);
?>
However it will not help you to change current request headers because of this:
To run the sub-request, all buffers are terminated and flushed to the
browser, pending headers are sent too.
Which means, that you can not send headers anymore. You should consider usage of cURL instead:
<?php
header('Content-Type: text/plain; charset=utf-8');
$cUrl = curl_init();
curl_setopt($cUrl, CURLOPT_URL, "http://somewhere/somepage.php");
curl_setopt($cUrl, CURLOPT_HEADER, true);
curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($cUrl);
curl_close($cUrl);
print_r($response);
?>
You could use the HTTP Library - http://au1.php.net/manual/en/httprequest.send.php

How to forward/redirect an HTTP PUT Request with PHP?

I receive HTTP PUT requests on a server and I would like to redirect / forward these requests to an other server.
I handle the PUT request on both server with PHP.
The PUT request is using basic HTTP authentication.
Here is an example :
www.myserver.com/service/put/myfile.xml
redirect to
www.myotherserver.com/service/put/myfile.xml
How can I do this without saving the file on my first server and resending a PUT request using CURL?
Thanks!
HTTP/1.1 defines status code 307 for such redirect. However, PUT is normally used by client software and you can pretty much assume no one honors 307.
The most efficient way to do this is to setup a proxy on Apache to redirect the request to the new URL.
This is how you can proxy it in PHP,
$data = file_get_contents('php://input');
$mem = fopen('php://memory');
fwrite($mem, $data);
rewind($mem);
$ch = curl_init($new_url);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $mem);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
fclose($meme);
Not possible. A redirect is implicitly a GET request. You'll need to have to play for a proxy using curl.
Saving on disk is technically also not necessary, you could just pipe the reponse body directly to the request body of Curl. But since I've never done this in PHP (in Java it's a piece of cake), I can't give a more detailed answer about that.

Categories