PHP, How to Redirect/Forward HTTP Request with header and body?

前端 未结 3 1382
故里飘歌
故里飘歌 2021-01-30 09:14

I have a PHP page, main.php which is on server 1.

I have a PHP page main.php (same page, different code) on server 2.

main.php is a WebService.

I would l

相关标签:
3条回答
  • 2021-01-30 10:03

    If you have access to the Apache server config you can create a virtualhost with the following settings:

    ProxyPreserveHost Off
    ProxyPass / http://remotesite.domain.tld/
    ProxyPassReverse / http://remotesite.domain.tld/
    ProxyPassReverseCookieDomain remotesite.domain.tld proxysite.tld
    

    You'll need to enable mod_proxy and mod_proxy_http for this. Substitute remotesite.domain.tld to the site you forward to, and proxysite.tld to the forwarder.

    If you don't have access to the server config files, you can still do in php, by manually setting up curl and forward everything.

    <?php
    
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
    
    /* Set it true for debugging. */
    $logHeaders = FALSE;
    
    /* Site to forward requests to.  */
    $site = 'http://remotesite.domain.tld/';
    
    /* Domains to use when rewriting some headers. */
    $remoteDomain = 'remotesite.domain.tld';
    $proxyDomain = 'proxysite.tld';
    
    $request = $_SERVER['REQUEST_URI'];
    
    $ch = curl_init();
    
    /* If there was a POST request, then forward that as well.*/
    if ($_SERVER['REQUEST_METHOD'] == 'POST')
    {
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
    }
    curl_setopt($ch, CURLOPT_URL, $site . $request);
    curl_setopt($ch, CURLOPT_HEADER, TRUE);
    
    $headers = getallheaders();
    
    /* Translate some headers to make the remote party think we actually browsing that site. */
    $extraHeaders = array();
    if (isset($headers['Referer'])) 
    {
        $extraHeaders[] = 'Referer: '. str_replace($proxyDomain, $remoteDomain, $headers['Referer']);
    }
    if (isset($headers['Origin'])) 
    {
        $extraHeaders[] = 'Origin: '. str_replace($proxyDomain, $remoteDomain, $headers['Origin']);
    }
    
    /* Forward cookie as it came.  */
    curl_setopt($ch, CURLOPT_HTTPHEADER, $extraHeaders);
    if (isset($headers['Cookie']))
    {
        curl_setopt($ch, CURLOPT_COOKIE, $headers['Cookie']);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    
    if ($logHeaders)
    {
        $f = fopen("headers.txt", "a");
        curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
        curl_setopt($ch, CURLOPT_STDERR, $f);
    }
    
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $response = curl_exec($ch);
    
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($response, 0, $header_size);
    $body = substr($response, $header_size);
    
    $headerArray = explode(PHP_EOL, $headers);
    
    /* Process response headers. */
    foreach($headerArray as $header)
    {
        $colonPos = strpos($header, ':');
        if ($colonPos !== FALSE) 
        {
            $headerName = substr($header, 0, $colonPos);
            
            /* Ignore content headers, let the webserver decide how to deal with the content. */
            if (trim($headerName) == 'Content-Encoding') continue;
            if (trim($headerName) == 'Content-Length') continue;
            if (trim($headerName) == 'Transfer-Encoding') continue;
            if (trim($headerName) == 'Location') continue;
            /* -- */
            /* Change cookie domain for the proxy */
            if (trim($headerName) == 'Set-Cookie')
            {
                $header = str_replace('domain='.$remoteDomain, 'domain='.$proxyDomain, $header);
            }
            /* -- */
            
        }
        header($header, FALSE);
    }
    
    echo $body;
    
    if ($logHeaders)
    {
        fclose($f);
    }
    curl_close($ch);
    
    ?>
    

    EDIT:

    And of course the script must be in the root directory of a (sub)domain. And you should have a .htaccess that rewrites everything to it:

    RewriteEngine On
    RewriteRule .* index.php
    
    0 讨论(0)
  • 2021-01-30 10:06

    this is the solution i have found (there might be better)

     public static function getResponse ($url,$headers,$body)
        {
            $params = '?' . http_build_query($headers);
    
            $redirect_url = $url . $params;
    
            $ch = curl_init($redirect_url);
    
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $response = curl_exec($ch);
    
            if (!isset($response))
                return null;
            return $response;
        }
    
    0 讨论(0)
  • 2021-01-30 10:10

    I have used the code by Rehmat and Calmarius and made a few changes so now it handles multiple fields with same name like

    <input type="text" name="example[]">
    <input type="text" name="example[]">
    <input type="text" name="example[]">
    

    and to upload files too, including multiple files that use the same field name.

    here is goes:

    <?php
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
    
    class proxy {
        private $logHeaders     = false;
        
        /* Site to forward requests to.  */
        private $site           = 'http://redirectToSite';
        /* Domains to use when rewriting some headers. */
        private $remoteDomain   = 'redirectToSite';
        private $proxyDomain    = 'yourproxydomain.com';
    
        public function __construct() {
            $request = $_SERVER['REQUEST_URI'];
            $ch = curl_init();
    
            /* If there was a POST request, then forward that as well.*/
            if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                $post   = $this->sanitizePostFields($_POST);
                $files  = $this->sanitizeFiles($_FILES);
                if ($files) {
                    $post = array_merge($post, $files);
                }
                
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
                /*
                // this is enough if not uploading files
                curl_setopt(
                    $ch,
                    CURLOPT_POSTFIELDS,
                    http_build_query($_POST)
                );
                */
            }
            
            curl_setopt($ch, CURLOPT_URL, $this->site . $request);
            curl_setopt($ch, CURLOPT_HEADER, TRUE);
    
            $headers = getallheaders();
    
            /*
                Translate some headers to make the remote party think we
                actually browsing that site.
            */
            $extraHeaders = array();
            if (isset($headers['Referer'])) {
                $extraHeaders[] = 'Referer: '. str_replace(
                    $this->proxyDomain,
                    $this->remoteDomain,
                    $headers['Referer']
                );
            }
            if (isset($headers['Origin'])) {
                $extraHeaders[] = 'Origin: '. str_replace(
                    $this->proxyDomain,
                    $this->remoteDomain,
                    $headers['Origin']
                );
            }
    
            /*
                Forward cookie as it came.
            */
            curl_setopt($ch, CURLOPT_HTTPHEADER, $extraHeaders);
            if (isset($headers['Cookie'])) {
                curl_setopt($ch, CURLOPT_COOKIE, $headers['Cookie']);
            }
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    
            if ($this->logHeaders) {
                $f = fopen("headers.txt", "a");
                curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
                curl_setopt($ch, CURLOPT_STDERR, $f);
            }
    
            //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            $response = curl_exec($ch);
    
            $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
            $headers = substr($response, 0, $header_size);
            $body = substr($response, $header_size);
    
            $headerArray = explode(PHP_EOL, $headers);
    
            /* Process response headers. */
            foreach($headerArray as $header) {
                $colonPos = strpos($header, ':');
                if ($colonPos !== FALSE) {
                    $headerName = substr($header, 0, $colonPos);
    
                    /*
                        Ignore content headers, let the webserver decide how to
                        deal with the content.
                    */
                    if (trim($headerName) == 'Content-Encoding') continue;
                    if (trim($headerName) == 'Content-Length') continue;
                    if (trim($headerName) == 'Transfer-Encoding') continue;
                    
                    //if (trim($headerName) == 'Location') continue;
                    
                    /* -- */
                    /* Change cookie domain for the proxy */
                    if (trim($headerName) == 'Set-Cookie') {
                        $header = str_replace(
                            'domain='.$this->remoteDomain,
                            'domain='.$this->proxyDomain,
                            $header
                        );
                    }
                    /* -- */
                    
                    if (trim($headerName) == 'Location') {
                        $header = str_replace(
                            $this->remoteDomain,
                            $this->proxyDomain,
                            $header
                        );
                    }
                }
                
                header($header, FALSE);
            }
    
            echo $body;
    
            if ($this->logHeaders) {
                fclose($f);
            }
            
            curl_close($ch);
        }
    
        private function sanitizePostFields($post, $fieldName = '') {
            if (empty($post)) { return false; }
            if (!is_array($post)) { return false; }
            
            $result = [];
            
            foreach ($post as $k => $v) {
                if (is_string($v)) {
                    $result[($fieldName ? "{$fieldName}[{$k}]" : $k)] = $v;
                }
                elseif (is_array($v)) {
                    $result = array_merge(
                        $result,
                        $this->sanitizePostFields($v, $k)
                    );
                }
            }
            
            return $result;
        }
    
        private function sanitizeFiles($files) {
            if (empty($files)) { return false; }
            if (!is_array($files)) { return false; }
            
            $result = [];
            
            foreach ($files as $k => $v) {
                if (empty($v['name'])) { continue; }
                
                if (is_array($v['name'])) {
                    // more than one file using the same name field[]
                    $nFields = count($v['name']);
                    for ($i = 0; $i < $nFields; $i++) {
                        if (empty($v['tmp_name'][$i])) { continue; }
                        $curl_file_upload = new CURLFile(
                            $v['tmp_name'][$i],
                            $v['type'][$i],
                            $v['name'][$i]
                        );
                        $result["{$k}[{$i}]"] = $curl_file_upload;
                    }
                }
                else {
                    $curl_file_upload = new CURLFile(
                        $v['tmp_name'],
                        $v['type'],
                        $v['name']
                    );
                    $result[$k] = $curl_file_upload;
                }
            }
            
            return $result;
        }
        
    }
    
    $proxy = new proxy();
    
    0 讨论(0)
提交回复
热议问题